diff options
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 1217 |
1 files changed, 714 insertions, 503 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 8ab1b9bc3..5b779b63d 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -5,15 +5,17 @@ */ #include <ctype.h> -#include <limits.h> #include <stdlib.h> #include <string.h> +#include <math.h> #include <mruby.h> #include <mruby/compile.h> #include <mruby/proc.h> +#include <mruby/dump.h> #include <mruby/numeric.h> #include <mruby/string.h> #include <mruby/debug.h> +#include <mruby/presym.h> #include "node.h" #include <mruby/opcode.h> #include <mruby/re.h> @@ -38,8 +40,8 @@ enum looptype { struct loopinfo { enum looptype type; - int pc0, pc1, pc2, pc3, acc; - int ensure_level; + uint32_t pc0, pc1, pc2, pc3; + int acc; struct loopinfo *prev; }; @@ -53,15 +55,14 @@ typedef struct scope { node *lv; uint16_t sp; - uint16_t pc; - uint16_t lastpc; - uint16_t lastlabel; + uint32_t pc; + uint32_t lastpc; + uint32_t lastlabel; int ainfo:15; mrb_bool mscope:1; struct loopinfo *loop; - int ensure_level; - char const *filename; + mrb_sym filename_sym; uint16_t lineno; mrb_code *iseq; @@ -69,6 +70,10 @@ typedef struct scope { uint32_t icapa; mrb_irep *irep; + mrb_pool_value *pool; + mrb_sym *syms; + mrb_irep **reps; + struct mrb_irep_catch_handler *catch_table; uint32_t pcapa, scapa, rcapa; uint16_t nlocals; @@ -88,6 +93,15 @@ static struct loopinfo *loop_push(codegen_scope *s, enum looptype t); static void loop_break(codegen_scope *s, node *tree); static void loop_pop(codegen_scope *s, int val); +/* + * The search for catch handlers starts at the end of the table in mrb_vm_run(). + * Therefore, the next handler to be added must meet one of the following conditions. + * - Larger start position + * - Same start position but smaller end position + */ +static int catch_handler_new(codegen_scope *s); +static void catch_handler_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target); + static void gen_assignment(codegen_scope *s, node *tree, int sp, int val); static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val); @@ -100,16 +114,37 @@ codegen_error(codegen_scope *s, const char *message) if (!s) return; while (s->prev) { codegen_scope *tmp = s->prev; - mrb_free(s->mrb, s->iseq); + if (s->irep) { + mrb_free(s->mrb, s->iseq); + for (int i=0; i<s->irep->plen; i++) { + mrb_pool_value *pv = &s->pool[i]; + if ((pv->tt & 0x3) == IREP_TT_STR || pv->tt == IREP_TT_BIGINT) { + mrb_free(s->mrb, (void*)pv->u.str); + } + } + mrb_free(s->mrb, s->pool); + mrb_free(s->mrb, s->syms); + mrb_free(s->mrb, s->catch_table); + if (s->reps) { + /* copied from mrb_irep_free() in state.c */ + for (int i=0; i<s->irep->rlen; i++) { + if (s->reps[i]) + mrb_irep_decref(s->mrb, (mrb_irep*)s->reps[i]); + } + mrb_free(s->mrb, s->reps); + } + mrb_free(s->mrb, s->lines); + } mrb_pool_close(s->mpool); s = tmp; } -#ifndef MRB_DISABLE_STDIO - if (s->filename && s->lineno) { - fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); +#ifndef MRB_NO_STDIO + if (s->filename_sym && s->lineno) { + const char *filename = mrb_sym_name_len(s->mrb, s->filename_sym, NULL); + fprintf(stderr, "%s:%d: %s\n", filename, s->lineno, message); } else { - fprintf(stderr, "codegen error: %s\n", message); + fprintf(stderr, "%s\n", message); } #endif MRB_THROW(&s->jmp); @@ -125,15 +160,6 @@ codegen_palloc(codegen_scope *s, size_t len) } static void* -codegen_malloc(codegen_scope *s, size_t len) -{ - void *p = mrb_malloc_simple(s->mrb, len); - - if (!p) codegen_error(s, "mrb_malloc"); - return p; -} - -static void* codegen_realloc(codegen_scope *s, void *p, size_t len) { p = mrb_realloc_simple(s->mrb, p, len); @@ -151,22 +177,26 @@ new_label(codegen_scope *s) static void emit_B(codegen_scope *s, uint32_t pc, uint8_t i) { - if (pc >= MAXARG_S || s->icapa >= MAXARG_S) { - codegen_error(s, "too big code block"); - } if (pc >= s->icapa) { - s->icapa *= 2; - if (s->icapa > MAXARG_S) { - s->icapa = MAXARG_S; + if (pc == UINT32_MAX) { + codegen_error(s, "too big code block"); + } + if (pc >= UINT32_MAX / 2) { + pc = UINT32_MAX; + } + else { + s->icapa *= 2; } s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); if (s->lines) { s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa); - s->irep->lines = s->lines; } } if (s->lines) { - s->lines[pc] = s->lineno; + if (s->lineno > 0 || pc == 0) + s->lines[pc] = s->lineno; + else + s->lines[pc] = s->lines[pc-1]; } s->iseq[pc] = i; } @@ -261,6 +291,14 @@ genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b) } static void +genop_2SS(codegen_scope *s, mrb_code i, uint16_t a, uint32_t b) +{ + genop_1(s, i, a); + gen_S(s, b>>16); + gen_S(s, b&0xffff); +} + +static void genop_W(codegen_scope *s, mrb_code i, uint32_t a) { uint8_t a1 = (a>>16) & 0xff; @@ -277,8 +315,7 @@ genop_W(codegen_scope *s, mrb_code i, uint32_t a) #define NOVAL 0 #define VAL 1 -//static -mrb_bool +static mrb_bool no_optimize(codegen_scope *s) { if (s && s->parser && s->parser->no_optimize) @@ -286,23 +323,14 @@ no_optimize(codegen_scope *s) return FALSE; } -static -mrb_bool -on_eval(codegen_scope *s) -{ - if (s && s->parser && s->parser->on_eval) - return TRUE; - return FALSE; -} - struct mrb_insn_data -mrb_decode_insn(mrb_code *pc) +mrb_decode_insn(const mrb_code *pc) { struct mrb_insn_data data = { 0 }; mrb_code insn = READ_B(); uint16_t a = 0; uint16_t b = 0; - uint8_t c = 0; + uint16_t c = 0; switch (insn) { #define FETCH_Z() /* empty */ @@ -363,22 +391,44 @@ no_peephole(codegen_scope *s) return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc; } -static uint16_t -genjmp(codegen_scope *s, mrb_code i, uint16_t pc) +#define JMPLINK_START UINT32_MAX + +static void +gen_jmpdst(codegen_scope *s, uint32_t pc) +{ + + if (pc == JMPLINK_START) { + gen_S(s, 0); + } + else { + uint32_t pos2 = s->pc+2; + int32_t off = pc - pos2; + + if (off > INT16_MAX || INT16_MIN > off) { + codegen_error(s, "too big jump offset"); + } + gen_S(s, (uint16_t)off); + } +} + +static uint32_t +genjmp(codegen_scope *s, mrb_code i, uint32_t pc) { - uint16_t pos; + uint32_t pos; s->lastpc = s->pc; gen_B(s, i); pos = s->pc; - gen_S(s, pc); + gen_jmpdst(s, pc); return pos; } -static uint16_t -genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) +#define genjmp_0(s,i) genjmp(s,i,JMPLINK_START) + +static uint32_t +genjmp2(codegen_scope *s, mrb_code i, uint16_t a, uint32_t pc, int val) { - uint16_t pos; + uint32_t pos; if (!no_peephole(s) && !val) { struct mrb_insn_data data = mrb_last_insn(s); @@ -394,27 +444,24 @@ genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) gen_B(s, OP_EXT1); gen_B(s, i); gen_S(s, a); - pos = s->pc; - gen_S(s, pc); } else { gen_B(s, i); gen_B(s, (uint8_t)a); - pos = s->pc; - gen_S(s, pc); } + pos = s->pc; + gen_jmpdst(s, pc); return pos; } +#define genjmp2_0(s,i,a,val) genjmp2(s,i,a,JMPLINK_START,val) + static void gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) { if (no_peephole(s)) { normal: genop_2(s, OP_MOVE, dst, src); - if (on_eval(s)) { - genop_0(s, OP_NOP); - } return; } else { @@ -434,7 +481,8 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) s->pc = s->lastpc; genop_1(s, data.insn, dst); break; - case OP_LOADI: case OP_LOADINEG: case OP_LOADL: case OP_LOADSYM: + case OP_LOADI: case OP_LOADINEG: + case OP_LOADL: case OP_LOADSYM: case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV: case OP_GETCONST: case OP_STRING: case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH: @@ -468,11 +516,11 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src) } static void -gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) +gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst) { if (no_peephole(s)) { normal: - genop_2(s, op, dst, idx); + genop_1(s, op, dst); return; } else { @@ -493,10 +541,10 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) if (data.b >= 128) goto normal; s->pc = s->lastpc; if (op == OP_ADD) { - genop_3(s, OP_ADDI, dst, idx, (uint8_t)data.b); + genop_2(s, OP_ADDI, dst, (uint8_t)data.b); } else { - genop_3(s, OP_SUBI, dst, idx, (uint8_t)data.b); + genop_2(s, OP_SUBI, dst, (uint8_t)data.b); } break; default: @@ -505,21 +553,31 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst, uint16_t idx) } } -static int -dispatch(codegen_scope *s, uint16_t pos0) +static uint32_t +dispatch(codegen_scope *s, uint32_t pos0) { - uint16_t newpos; + int32_t pos1; + int32_t offset; + int16_t newpos; + + if (pos0 == JMPLINK_START) return 0; + pos1 = pos0 + 2; + offset = s->pc - pos1; + if (offset > INT16_MAX) { + codegen_error(s, "too big jmp offset"); + } s->lastlabel = s->pc; - newpos = PEEK_S(s->iseq+pos0); - emit_S(s, pos0, s->pc); - return newpos; + newpos = (int16_t)PEEK_S(s->iseq+pos0); + emit_S(s, pos0, (uint16_t)offset); + if (newpos == 0) return 0; + return pos1+newpos; } static void -dispatch_linked(codegen_scope *s, uint16_t pos) +dispatch_linked(codegen_scope *s, uint32_t pos) { - if (pos==0) return; + if (pos==JMPLINK_START) return; for (;;) { pos = dispatch(s, pos); if (pos==0) break; @@ -552,38 +610,91 @@ pop_n_(codegen_scope *s, int n) #define pop_n(n) pop_n_(s,n) #define cursp() (s->sp) -static inline int +static int +new_litbn(codegen_scope *s, const char *p, int base, mrb_bool neg) +{ + int i; + size_t plen; + mrb_pool_value *pv; + + plen = strlen(p); + if (plen > 255) { + codegen_error(s, "integer too big"); + } + for (i=0; i<s->irep->plen; i++) { + size_t len; + pv = &s->pool[i]; + if (pv->tt != IREP_TT_BIGINT) continue; + len = pv->u.str[0]; + if (len == plen && pv->u.str[1] == base && memcmp(pv->u.str+2, p, len) == 0) + return i; + } + + if (s->irep->plen == s->pcapa) { + s->pcapa *= 2; + s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa); + } + + pv = &s->pool[s->irep->plen]; + i = s->irep->plen++; + { + char *buf; + pv->tt = IREP_TT_BIGINT; + buf = (char*)codegen_realloc(s, NULL, plen+3); + buf[0] = (char)plen; + buf[1] = base; + if (neg) buf[1] = 0x80; + memcpy(buf+2, p, plen); + buf[plen+2] = '\0'; + pv->u.str = buf; + } + return i; +} + +static int new_lit(codegen_scope *s, mrb_value val) { int i; - mrb_value *pv; + mrb_pool_value *pv; switch (mrb_type(val)) { case MRB_TT_STRING: for (i=0; i<s->irep->plen; i++) { mrb_int len; - pv = &s->irep->pool[i]; - - if (mrb_type(*pv) != MRB_TT_STRING) continue; - if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue; - if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0) + pv = &s->pool[i]; + if (pv->tt & IREP_TT_NFLAG) continue; + len = pv->tt>>2; + if (RSTRING_LEN(val) != len) continue; + if (memcmp(pv->u.str, RSTRING_PTR(val), len) == 0) return i; } break; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: for (i=0; i<s->irep->plen; i++) { - pv = &s->irep->pool[i]; - if (mrb_type(*pv) != MRB_TT_FLOAT) continue; - if (mrb_float(*pv) == mrb_float(val)) return i; + mrb_float f1, f2; + pv = &s->pool[i]; + if (pv->tt != IREP_TT_FLOAT) continue; + pv = &s->pool[i]; + f1 = pv->u.f; + f2 = mrb_float(val); + if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i; } break; #endif - case MRB_TT_FIXNUM: + case MRB_TT_INTEGER: for (i=0; i<s->irep->plen; i++) { - pv = &s->irep->pool[i]; - if (!mrb_fixnum_p(*pv)) continue; - if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i; + mrb_int v = mrb_integer(val); + pv = &s->pool[i]; + if (pv->tt == IREP_TT_INT32) { + if (v == pv->u.i32) return i; + } +#ifdef MRB_64BIT + else if (pv->tt == IREP_TT_INT64) { + if (v == pv->u.i64) return i; + } + continue; +#endif } break; default: @@ -593,26 +704,43 @@ new_lit(codegen_scope *s, mrb_value val) if (s->irep->plen == s->pcapa) { s->pcapa *= 2; - s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa); + s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa); } - pv = &s->irep->pool[s->irep->plen]; + pv = &s->pool[s->irep->plen]; i = s->irep->plen++; switch (mrb_type(val)) { case MRB_TT_STRING: - *pv = mrb_str_pool(s->mrb, val); + if (RSTR_NOFREE_P(RSTRING(val))) { + pv->tt = (uint32_t)(RSTRING_LEN(val)<<2) | IREP_TT_SSTR; + pv->u.str = RSTRING_PTR(val); + } + else { + char *p; + mrb_int len = RSTRING_LEN(val); + pv->tt = (uint32_t)(len<<2) | IREP_TT_STR; + p = (char*)codegen_realloc(s, NULL, len+1); + memcpy(p, RSTRING_PTR(val), len); + p[len] = '\0'; + pv->u.str = p; + } break; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: -#ifdef MRB_WORD_BOXING - *pv = mrb_float_pool(s->mrb, mrb_float(val)); + pv->tt = IREP_TT_FLOAT; + pv->u.f = mrb_float(val); break; #endif + case MRB_TT_INTEGER: +#ifdef MRB_INT64 + pv->tt = IREP_TT_INT64; + pv->u.i64 = mrb_integer(val); +#else + pv->tt = IREP_TT_INT32; + pv->u.i32 = mrb_integer(val); #endif - case MRB_TT_FIXNUM: - *pv = val; break; default: @@ -622,9 +750,6 @@ new_lit(codegen_scope *s, mrb_value val) return i; } -/* maximum symbol numbers */ -#define MAXSYMLEN 0x10000 - static int new_sym(codegen_scope *s, mrb_sym sym) { @@ -634,13 +759,16 @@ new_sym(codegen_scope *s, mrb_sym sym) len = s->irep->slen; for (i=0; i<len; i++) { - if (s->irep->syms[i] == sym) return i; + if (s->syms[i] == sym) return i; } if (s->irep->slen >= s->scapa) { s->scapa *= 2; - s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa); + if (s->scapa > 0xffff) { + codegen_error(s, "too many symbols"); + } + s->syms = (mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->scapa); } - s->irep->syms[s->irep->slen] = sym; + s->syms[s->irep->slen] = sym; return s->irep->slen++; } @@ -676,6 +804,47 @@ lv_idx(codegen_scope *s, mrb_sym id) return 0; } +static int +search_upvar(codegen_scope *s, mrb_sym id, int *idx) +{ + const struct RProc *u; + int lv = 0; + codegen_scope *up = s->prev; + + while (up) { + *idx = lv_idx(up, id); + if (*idx > 0) { + return lv; + } + lv ++; + up = up->prev; + } + + if (lv < 1) lv = 1; + u = s->parser->upper; + while (u && !MRB_PROC_CFUNC_P(u)) { + const struct mrb_irep *ir = u->body.irep; + uint_fast16_t n = ir->nlocals; + int i; + + const mrb_sym *v = ir->lv; + if (v) { + for (i=1; n > 1; n--, v++, i++) { + if (*v == id) { + *idx = i; + return lv - 1; + } + } + } + if (MRB_PROC_SCOPE_P(u)) break; + u = u->upper; + lv ++; + } + + codegen_error(s, "Can't found local variables"); + return -1; /* not reached */ +} + static void for_body(codegen_scope *s, node *tree) { @@ -688,9 +857,6 @@ for_body(codegen_scope *s, node *tree) codegen(s, tree->cdr->car, VAL); /* generate loop-block */ s = scope_new(s->mrb, s, NULL); - if (s == NULL) { - raise_error(prev, "unexpected scope"); - } push(); /* push for a block parameter */ @@ -717,7 +883,7 @@ for_body(codegen_scope *s, node *tree) genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1); push();pop(); /* space for a block */ pop(); - idx = new_sym(s, mrb_intern_lit(s->mrb, "each")); + idx = new_sym(s, MRB_SYM_2(s->mrb, each)); genop_3(s, OP_SENDB, cursp(), idx, 0); } @@ -726,9 +892,6 @@ lambda_body(codegen_scope *s, node *tree, int blk) { codegen_scope *parent = s; s = scope_new(s->mrb, s, tree->car); - if (s == NULL) { - raise_error(parent, "unexpected scope"); - } s->mscope = !blk; @@ -737,27 +900,30 @@ lambda_body(codegen_scope *s, node *tree, int blk) lp->pc0 = new_label(s); } tree = tree->cdr; - if (tree->car) { + if (tree->car == NULL) { + genop_W(s, OP_ENTER, 0); + s->ainfo = 0; + } + else { mrb_aspec a; int ma, oa, ra, pa, ka, kd, ba; int pos, i; - node *n, *opt; + node *opt; + node *margs, *pargs; node *tail; /* mandatory arguments */ ma = node_len(tree->car->car); - n = tree->car->car; - while (n) { - n = n->cdr; - } + margs = tree->car->car; tail = tree->car->cdr->cdr->cdr->cdr; /* optional arguments */ oa = node_len(tree->car->cdr->car); /* rest argument? */ ra = tree->car->cdr->cdr->car ? 1 : 0; - /* mandatory arugments after rest argument */ + /* mandatory arguments after rest argument */ pa = node_len(tree->car->cdr->cdr->cdr->car); + pargs = tree->car->cdr->cdr->cdr->car; /* keyword arguments */ ka = tail? node_len(tail->cdr->car) : 0; /* keyword dictionary? */ @@ -777,27 +943,34 @@ lambda_body(codegen_scope *s, node *tree, int blk) s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */ | ((ra & 0x1) << 6) | ((pa & 0x1f) << 1) - | (kd & 0x1); + | ((ka | kd) != 0 ? 0x01 : 0x00); genop_W(s, OP_ENTER, a); /* generate jump table for optional arguments initializer */ pos = new_label(s); for (i=0; i<oa; i++) { new_label(s); - genjmp(s, OP_JMP, 0); + genjmp_0(s, OP_JMP); } if (oa > 0) { - genjmp(s, OP_JMP, 0); + genjmp_0(s, OP_JMP); } opt = tree->car->cdr->car; i = 0; while (opt) { int idx; + mrb_sym id = nsym(opt->car->car); dispatch(s, pos+i*3+1); codegen(s, opt->car->cdr, VAL); pop(); - idx = lv_idx(s, nsym(opt->car->car)); - gen_move(s, idx, cursp(), 0); + idx = lv_idx(s, id); + if (idx > 0) { + gen_move(s, idx, cursp(), 0); + } + else { + int lv = search_upvar(s, id, &idx); + genop_3(s, OP_GETUPVAR, cursp(), idx, lv); + } i++; opt = opt->cdr; } @@ -805,6 +978,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) dispatch(s, pos+i*3+1); } + /* keyword arguments */ if (tail) { node *kwds = tail->cdr->car; int kwrest = 0; @@ -823,12 +997,20 @@ lambda_body(codegen_scope *s, node *tree, int blk) mrb_assert(nint(kwd->car) == NODE_KW_ARG); if (def_arg) { - genop_2(s, OP_KEY_P, cursp(), new_sym(s, kwd_sym)); - jmpif_key_p = genjmp2(s, OP_JMPIF, cursp(), 0, 0); + int idx; + genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym)); + jmpif_key_p = genjmp2_0(s, OP_JMPIF, lv_idx(s, kwd_sym), NOVAL); codegen(s, def_arg, VAL); pop(); - gen_move(s, lv_idx(s, kwd_sym), cursp(), 0); - jmp_def_set = genjmp(s, OP_JMP, 0); + idx = lv_idx(s, kwd_sym); + if (idx > 0) { + gen_move(s, idx, cursp(), 0); + } + else { + int lv = search_upvar(s, kwd_sym, &idx); + genop_3(s, OP_GETUPVAR, cursp(), idx, lv); + } + jmp_def_set = genjmp_0(s, OP_JMP); dispatch(s, jmpif_key_p); } genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym)); @@ -843,7 +1025,34 @@ lambda_body(codegen_scope *s, node *tree, int blk) genop_0(s, OP_KEYEND); } } + + /* argument destructuring */ + if (margs) { + node *n = margs; + + pos = 1; + while (n) { + if (nint(n->car->car) == NODE_MASGN) { + gen_vmassignment(s, n->car->cdr->car, pos, NOVAL); + } + pos++; + n = n->cdr; + } + } + if (pargs) { + node *n = margs; + + pos = ma+oa+ra+1; + while (n) { + if (nint(n->car->car) == NODE_MASGN) { + gen_vmassignment(s, n->car->cdr->car, pos, NOVAL); + } + pos++; + n = n->cdr; + } + } } + codegen(s, tree->cdr->car, VAL); pop(); if (s->pc > 0) { @@ -860,9 +1069,6 @@ static int scope_body(codegen_scope *s, node *tree, int val) { codegen_scope *scope = scope_new(s->mrb, s, tree->car); - if (scope == NULL) { - codegen_error(s, "unexpected scope"); - } codegen(scope, tree->cdr, VAL); gen_return(scope, OP_RETURN, scope->sp-1); @@ -894,7 +1100,7 @@ attrsym(codegen_scope *s, mrb_sym a) mrb_int len; char *name2; - name = mrb_sym2name_len(s->mrb, a, &len); + name = mrb_sym_name_len(s->mrb, a, &len); name2 = (char *)codegen_palloc(s, (size_t)len + 1 /* '=' */ @@ -928,7 +1134,12 @@ gen_values(codegen_scope *s, node *t, int val, int extra) } else { pop_n(n); - genop_2(s, OP_ARRAY, cursp(), n); + if (n == 0 && is_splat) { + genop_1(s, OP_LOADNIL, cursp()); + } + else { + genop_2(s, OP_ARRAY, cursp(), n); + } push(); codegen(s, t->car, VAL); pop(); pop(); @@ -973,16 +1184,15 @@ static void gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) { mrb_sym sym = name ? name : nsym(tree->cdr->car); - int idx, skip = 0; + int skip = 0; int n = 0, noop = 0, sendv = 0, blk = 0; codegen(s, tree->car, VAL); /* receiver */ if (safe) { int recv = cursp()-1; gen_move(s, cursp(), recv, 1); - skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val); + skip = genjmp2_0(s, OP_JMPNIL, cursp(), val); } - idx = new_sym(s, sym); tree = tree->cdr->cdr->car; if (tree) { n = gen_values(s, tree->car, VAL, sp?1:0); @@ -1014,36 +1224,38 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) pop_n(n+1); { mrb_int symlen; - const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen); + const char *symname = mrb_sym_name_len(s->mrb, sym, &symlen); if (!noop && symlen == 1 && symname[0] == '+' && n == 1) { - gen_addsub(s, OP_ADD, cursp(), idx); + gen_addsub(s, OP_ADD, cursp()); } else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) { - gen_addsub(s, OP_SUB, cursp(), idx); + gen_addsub(s, OP_SUB, cursp()); } else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) { - genop_2(s, OP_MUL, cursp(), idx); + genop_1(s, OP_MUL, cursp()); } else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) { - genop_2(s, OP_DIV, cursp(), idx); + genop_1(s, OP_DIV, cursp()); } else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) { - genop_2(s, OP_LT, cursp(), idx); + genop_1(s, OP_LT, cursp()); } else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) { - genop_2(s, OP_LE, cursp(), idx); + genop_1(s, OP_LE, cursp()); } else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) { - genop_2(s, OP_GT, cursp(), idx); + genop_1(s, OP_GT, cursp()); } else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) { - genop_2(s, OP_GE, cursp(), idx); + genop_1(s, OP_GE, cursp()); } else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) { - genop_2(s, OP_EQ, cursp(), idx); + genop_1(s, OP_EQ, cursp()); } else { + int idx = new_sym(s, sym); + if (sendv) { genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx); } @@ -1072,30 +1284,24 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) idx = new_sym(s, nsym(tree)); genop_2(s, OP_SETGV, sp, idx); break; + case NODE_ARG: case NODE_LVAR: idx = lv_idx(s, nsym(tree)); if (idx > 0) { if (idx != sp) { gen_move(s, idx, sp, val); - if (val && on_eval(s)) genop_0(s, OP_NOP); } break; } else { /* upvar */ - int lv = 0; - codegen_scope *up = s->prev; - - while (up) { - idx = lv_idx(up, nsym(tree)); - if (idx > 0) { - genop_3(s, OP_SETUPVAR, sp, idx, lv); - break; - } - lv++; - up = up->prev; - } + int lv = search_upvar(s, nsym(tree), &idx); + genop_3(s, OP_SETUPVAR, sp, idx, lv); } break; + case NODE_NVAR: + idx = nint(tree); + codegen_error(s, "Can't assign to numbered parameter"); + break; case NODE_IVAR: idx = new_sym(s, nsym(tree)); genop_2(s, OP_SETIV, sp, idx); @@ -1137,9 +1343,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val) break; default: -#ifndef MRB_DISABLE_STDIO - fprintf(stderr, "unknown lhs %d\n", type); -#endif + codegen_error(s, "unknown lhs"); break; } if (val) push(); @@ -1179,7 +1383,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) pop_n(post+1); genop_3(s, OP_APOST, cursp(), n, post); n = 1; - if (t->car) { /* rest */ + if (t->car && t->car != (node*)-1) { /* rest */ gen_assignment(s, t->car, cursp(), NOVAL); } if (t->cdr && t->cdr->car) { @@ -1266,70 +1470,37 @@ raise_error(codegen_scope *s, const char *msg) genop_1(s, OP_ERR, idx); } -#ifndef MRB_WITHOUT_FLOAT -static double -readint_float(codegen_scope *s, const char *p, int base) -{ - const char *e = p + strlen(p); - double f = 0; - int n; - - if (*p == '+') p++; - while (p < e) { - char c = *p; - c = tolower((unsigned char)c); - for (n=0; n<base; n++) { - if (mrb_digitmap[n] == c) { - f *= base; - f += n; - break; - } - } - if (n == base) { - codegen_error(s, "malformed readint input"); - } - p++; - } - return f; -} -#endif - static mrb_int -readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow) +readint(codegen_scope *s, const char *p, int base, mrb_bool *overflow) { const char *e = p + strlen(p); mrb_int result = 0; - int n; mrb_assert(base >= 2 && base <= 36); if (*p == '+') p++; while (p < e) { + int n; char c = *p; - c = tolower((unsigned char)c); - for (n=0; n<base; n++) { - if (mrb_digitmap[n] == c) { - break; - } - } - if (n == base) { + switch (c) { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + n = c - '0'; break; + case '8': case '9': + n = c - '0'; break; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + n = c - 'a' + 10; break; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + n = c - 'A' + 10; break; + default: codegen_error(s, "malformed readint input"); + *overflow = TRUE; + /* not reached */ + return result; } - - if (neg) { - if ((MRB_INT_MIN + n)/base > result) { - *overflow = TRUE; - return 0; - } - result *= base; - result -= n; - } - else { - if ((MRB_INT_MAX - n)/base < result) { - *overflow = TRUE; - return 0; - } - result *= base; - result += n; + if (mrb_int_mul_overflow(result, base, &result) || + mrb_int_add_overflow(result, n, &result)) { + *overflow = TRUE; + return 0; } p++; } @@ -1370,11 +1541,14 @@ codegen(codegen_scope *s, node *tree, int val) codegen_error(s, "too complex expression"); } if (s->irep && s->filename_index != tree->filename_index) { - s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); - mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc); + mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index); + const char *filename = mrb_sym_name_len(s->mrb, fname, NULL); + + mrb_debug_info_append_file(s->mrb, s->irep->debug_info, + filename, s->lines, s->debug_start_pos, s->pc); s->debug_start_pos = s->pc; s->filename_index = tree->filename_index; - s->filename = mrb_parser_get_filename(s->parser, tree->filename_index); + s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index); } nt = nint(tree->car); @@ -1394,21 +1568,25 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_RESCUE: { - int noexc, exend, pos1, pos2, tmp; + int noexc; + uint32_t exend, pos1, pos2, tmp; struct loopinfo *lp; + int catch_entry, begin, end; if (tree->car == NULL) goto exit; lp = loop_push(s, LOOP_BEGIN); lp->pc0 = new_label(s); - lp->pc1 = genjmp(s, OP_ONERR, 0); + catch_entry = catch_handler_new(s); + begin = s->pc; codegen(s, tree->car, VAL); pop(); lp->type = LOOP_RESCUE; - noexc = genjmp(s, OP_JMP, 0); - dispatch(s, lp->pc1); + end = s->pc; + noexc = genjmp_0(s, OP_JMP); + catch_handler_set(s, catch_entry, MRB_CATCH_RESCUE, begin, end, s->pc); tree = tree->cdr; - exend = 0; - pos1 = 0; + exend = JMPLINK_START; + pos1 = JMPLINK_START; if (tree->car) { node *n2 = tree->car; int exc = cursp(); @@ -1419,22 +1597,22 @@ codegen(codegen_scope *s, node *tree, int val) node *n3 = n2->car; node *n4 = n3->car; - if (pos1) dispatch(s, pos1); - pos2 = 0; + dispatch(s, pos1); + pos2 = JMPLINK_START; do { if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) { codegen(s, n4->car, VAL); gen_move(s, cursp(), exc, 0); push_n(2); pop_n(2); /* space for one arg and a block */ pop(); - genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1); + genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, __case_eqq)), 1); } else { if (n4) { codegen(s, n4->car, VAL); } else { - genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError"))); + genop_2(s, OP_GETCONST, cursp(), new_sym(s, MRB_SYM_2(s->mrb, StandardError))); push(); } pop(); @@ -1446,7 +1624,7 @@ codegen(codegen_scope *s, node *tree, int val) n4 = n4->cdr; } } while (n4); - pos1 = genjmp(s, OP_JMP, 0); + pos1 = genjmp_0(s, OP_JMP); dispatch_linked(s, pos2); pop(); @@ -1462,15 +1640,14 @@ codegen(codegen_scope *s, node *tree, int val) n2 = n2->cdr; push(); } - if (pos1) { + if (pos1 != JMPLINK_START) { dispatch(s, pos1); - genop_1(s, OP_RAISE, exc); + genop_1(s, OP_RAISEIF, exc); } } pop(); tree = tree->cdr; dispatch(s, noexc); - genop_1(s, OP_POPERR, 1); if (tree->car) { codegen(s, tree->car, val); } @@ -1486,14 +1663,22 @@ codegen(codegen_scope *s, node *tree, int val) if (!tree->cdr || !tree->cdr->cdr || (nint(tree->cdr->cdr->car) == NODE_BEGIN && tree->cdr->cdr->cdr)) { + int catch_entry, begin, end, target; int idx; - s->ensure_level++; - idx = scope_body(s, tree->cdr, NOVAL); - genop_1(s, OP_EPUSH, idx); + catch_entry = catch_handler_new(s); + begin = s->pc; codegen(s, tree->car, val); - s->ensure_level--; - genop_1(s, OP_EPOP, 1); + end = target = s->pc; + push(); + idx = cursp(); + genop_1(s, OP_EXCEPT, idx); + push(); + codegen(s, tree->cdr->cdr, NOVAL); + pop(); + genop_1(s, OP_RAISEIF, idx); + pop(); + catch_handler_set(s, catch_entry, MRB_CATCH_ENSURE, begin, end, target); } else { /* empty ensure ignored */ codegen(s, tree->car, val); @@ -1520,7 +1705,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_IF: { - int pos1, pos2; + int pos1, pos2, nil_p = FALSE; node *elsepart = tree->cdr->cdr->car; if (!tree->car) { @@ -1537,32 +1722,59 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_NIL: codegen(s, elsepart, val); goto exit; + case NODE_CALL: + { + node *n = tree->car->cdr; + mrb_sym mid = nsym(n->cdr->car); + mrb_sym mnil = MRB_SYM_Q_2(s->mrb, nil); + if (mid == mnil && n->cdr->cdr->car == NULL) { + nil_p = TRUE; + codegen(s, n->car, VAL); + } + } + break; + } + if (!nil_p) { + codegen(s, tree->car, VAL); } - codegen(s, tree->car, VAL); pop(); - pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val); - - codegen(s, tree->cdr->car, val); - if (elsepart) { + if (val || tree->cdr->car) { + if (nil_p) { + pos2 = genjmp2_0(s, OP_JMPNIL, cursp(), val); + pos1 = genjmp_0(s, OP_JMP); + dispatch(s, pos2); + } + else { + pos1 = genjmp2_0(s, OP_JMPNOT, cursp(), val); + } + codegen(s, tree->cdr->car, val); if (val) pop(); - pos2 = genjmp(s, OP_JMP, 0); - dispatch(s, pos1); - codegen(s, elsepart, val); - dispatch(s, pos2); - } - else { - if (val) { - pop(); - pos2 = genjmp(s, OP_JMP, 0); + if (elsepart || val) { + pos2 = genjmp_0(s, OP_JMP); dispatch(s, pos1); - genop_1(s, OP_LOADNIL, cursp()); + codegen(s, elsepart, val); dispatch(s, pos2); - push(); } else { dispatch(s, pos1); } } + else { /* empty then-part */ + if (elsepart) { + if (nil_p) { + pos1 = genjmp2_0(s, OP_JMPNIL, cursp(), val); + } + else { + pos1 = genjmp2_0(s, OP_JMPIF, cursp(), val); + } + codegen(s, elsepart, val); + dispatch(s, pos1); + } + else if (val && !nil_p) { + genop_1(s, OP_LOADNIL, cursp()); + push(); + } + } } break; @@ -1572,7 +1784,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); - pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val); + pos = genjmp2_0(s, OP_JMPNOT, cursp(), val); codegen(s, tree->cdr, val); dispatch(s, pos); } @@ -1584,7 +1796,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); - pos = genjmp2(s, OP_JMPIF, cursp(), 0, val); + pos = genjmp2_0(s, OP_JMPIF, cursp(), val); codegen(s, tree->cdr, val); dispatch(s, pos); } @@ -1595,7 +1807,7 @@ codegen(codegen_scope *s, node *tree, int val) struct loopinfo *lp = loop_push(s, LOOP_NORMAL); lp->pc0 = new_label(s); - lp->pc1 = genjmp(s, OP_JMP, 0); + lp->pc1 = genjmp_0(s, OP_JMP); lp->pc2 = new_label(s); codegen(s, tree->cdr, NOVAL); dispatch(s, lp->pc1); @@ -1612,7 +1824,7 @@ codegen(codegen_scope *s, node *tree, int val) struct loopinfo *lp = loop_push(s, LOOP_NORMAL); lp->pc0 = new_label(s); - lp->pc1 = genjmp(s, OP_JMP, 0); + lp->pc1 = genjmp_0(s, OP_JMP); lp->pc2 = new_label(s); codegen(s, tree->cdr, NOVAL); dispatch(s, lp->pc1); @@ -1632,10 +1844,10 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_CASE: { int head = 0; - int pos1, pos2, pos3, tmp; + uint32_t pos1, pos2, pos3, tmp; node *n; - pos3 = 0; + pos3 = JMPLINK_START; if (tree->car) { head = cursp(); codegen(s, tree->car, VAL); @@ -1643,17 +1855,17 @@ codegen(codegen_scope *s, node *tree, int val) tree = tree->cdr; while (tree) { n = tree->car->car; - pos1 = pos2 = 0; + pos1 = pos2 = JMPLINK_START; while (n) { codegen(s, n->car, VAL); if (head) { gen_move(s, cursp(), head, 0); push(); push(); pop(); pop(); pop(); if (nint(n->car->car) == NODE_SPLAT) { - genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1); + genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, __case_eqq)), 1); } else { - genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1); + genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_OPSYM_2(s->mrb, eqq)), 1); } } else { @@ -1664,20 +1876,20 @@ codegen(codegen_scope *s, node *tree, int val) n = n->cdr; } if (tree->car->car) { - pos1 = genjmp(s, OP_JMP, 0); + pos1 = genjmp_0(s, OP_JMP); dispatch_linked(s, pos2); } codegen(s, tree->car->cdr, val); if (val) pop(); tmp = genjmp(s, OP_JMP, pos3); pos3 = tmp; - if (pos1) dispatch(s, pos1); + dispatch(s, pos1); tree = tree->cdr; } if (val) { - int pos = cursp(); + uint32_t pos = cursp(); genop_1(s, OP_LOADNIL, cursp()); - if (pos3) dispatch_linked(s, pos3); + if (pos3 != JMPLINK_START) dispatch_linked(s, pos3); if (head) pop(); if (cursp() != pos) { gen_move(s, cursp(), pos, 0); @@ -1685,7 +1897,7 @@ codegen(codegen_scope *s, node *tree, int val) push(); } else { - if (pos3) { + if (pos3 != JMPLINK_START) { dispatch_linked(s, pos3); } if (head) { @@ -1800,7 +2012,7 @@ codegen(codegen_scope *s, node *tree, int val) len++; } tree = tree->cdr; - if (val && len == 255) { + if (val && cursp() > 127) { pop_n(len*2); if (!update) { genop_2(s, OP_HASH, cursp(), len); @@ -1922,24 +2134,26 @@ codegen(codegen_scope *s, node *tree, int val) { mrb_sym sym = nsym(tree->cdr->car); mrb_int len; - const char *name = mrb_sym2name_len(s->mrb, sym, &len); + const char *name = mrb_sym_name_len(s->mrb, sym, &len); int idx, callargs = -1, vsp = -1; if ((len == 2 && name[0] == '|' && name[1] == '|') && (nint(tree->car->car) == NODE_CONST || nint(tree->car->car) == NODE_CVAR)) { - int onerr, noexc, exc; + int catch_entry, begin, end; + int noexc, exc; struct loopinfo *lp; - onerr = genjmp(s, OP_ONERR, 0); lp = loop_push(s, LOOP_BEGIN); - lp->pc1 = onerr; + lp->pc0 = new_label(s); + catch_entry = catch_handler_new(s); + begin = s->pc; exc = cursp(); codegen(s, tree->car, VAL); + end = s->pc; + noexc = genjmp_0(s, OP_JMP); lp->type = LOOP_RESCUE; - genop_1(s, OP_POPERR, 1); - noexc = genjmp(s, OP_JMP, 0); - dispatch(s, onerr); + catch_handler_set(s, catch_entry, MRB_CATCH_RESCUE, begin, end, s->pc); genop_1(s, OP_EXCEPT, exc); genop_1(s, OP_LOADF, exc); dispatch(s, noexc); @@ -1990,10 +2204,10 @@ codegen(codegen_scope *s, node *tree, int val) if (vsp >= 0) { gen_move(s, vsp, cursp(), 1); } - pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val); + pos = genjmp2_0(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), val); } else { - pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val); + pos = genjmp2_0(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), val); } codegen(s, tree->cdr->cdr->car, VAL); pop(); @@ -2023,32 +2237,32 @@ codegen(codegen_scope *s, node *tree, int val) push(); pop(); pop(); pop(); - idx = new_sym(s, sym); if (len == 1 && name[0] == '+') { - gen_addsub(s, OP_ADD, cursp(), idx); + gen_addsub(s, OP_ADD, cursp()); } else if (len == 1 && name[0] == '-') { - gen_addsub(s, OP_SUB, cursp(), idx); + gen_addsub(s, OP_SUB, cursp()); } else if (len == 1 && name[0] == '*') { - genop_2(s, OP_MUL, cursp(), idx); + genop_1(s, OP_MUL, cursp()); } else if (len == 1 && name[0] == '/') { - genop_2(s, OP_DIV, cursp(), idx); + genop_1(s, OP_DIV, cursp()); } else if (len == 1 && name[0] == '<') { - genop_2(s, OP_LT, cursp(), idx); + genop_1(s, OP_LT, cursp()); } else if (len == 2 && name[0] == '<' && name[1] == '=') { - genop_2(s, OP_LE, cursp(), idx); + genop_1(s, OP_LE, cursp()); } else if (len == 1 && name[0] == '>') { - genop_2(s, OP_GT, cursp(), idx); + genop_1(s, OP_GT, cursp()); } else if (len == 2 && name[0] == '>' && name[1] == '=') { - genop_2(s, OP_GE, cursp(), idx); + genop_1(s, OP_GE, cursp()); } else { + idx = new_sym(s, sym); genop_3(s, OP_SEND, cursp(), idx, 1); } if (callargs < 0) { @@ -2124,7 +2338,9 @@ codegen(codegen_scope *s, node *tree, int val) s2 = s2->prev; if (!s2) break; } - if (s2) ainfo = s2->ainfo; + if (s2 && s2->ainfo > 0) { + ainfo = s2->ainfo; + } genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)); push(); push(); pop(); /* ARGARY pushes two values */ if (tree && tree->cdr) { @@ -2156,7 +2372,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_YIELD: { codegen_scope *s2 = s; - int lv = 0, ainfo = 0; + int lv = 0, ainfo = -1; int n = 0, sendv = 0; while (!s2->mscope) { @@ -2164,7 +2380,10 @@ codegen(codegen_scope *s, node *tree, int val) s2 = s2->prev; if (!s2) break; } - if (s2) ainfo = s2->ainfo; + if (s2) { + ainfo = s2->ainfo; + } + if (ainfo < 0) codegen_error(s, "invalid yield (SyntaxError)"); push(); if (tree) { n = gen_values(s, tree, VAL, 0); @@ -2177,7 +2396,7 @@ codegen(codegen_scope *s, node *tree, int val) pop_n(n+1); genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)); if (sendv) n = CALL_MAXARGS; - genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n); + genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, call)), n); if (val) push(); } break; @@ -2192,11 +2411,8 @@ codegen(codegen_scope *s, node *tree, int val) raise_error(s, "unexpected next"); } else if (s->loop->type == LOOP_NORMAL) { - if (s->ensure_level > s->loop->ensure_level) { - genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level); - } codegen(s, tree, NOVAL); - genjmp(s, OP_JMP, s->loop->pc0); + genjmp(s, OP_JMPUW, s->loop->pc0); } else { if (tree) { @@ -2216,10 +2432,7 @@ codegen(codegen_scope *s, node *tree, int val) raise_error(s, "unexpected redo"); } else { - if (s->ensure_level > s->loop->ensure_level) { - genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level); - } - genjmp(s, OP_JMP, s->loop->pc2); + genjmp(s, OP_JMPUW, s->loop->pc2); } if (val) push(); break; @@ -2227,32 +2440,16 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_RETRY: { const char *msg = "unexpected retry"; + const struct loopinfo *lp = s->loop; - if (!s->loop) { + while (lp && lp->type != LOOP_RESCUE) { + lp = lp->prev; + } + if (!lp) { raise_error(s, msg); } else { - struct loopinfo *lp = s->loop; - int n = 0; - - while (lp && lp->type != LOOP_RESCUE) { - if (lp->type == LOOP_BEGIN) { - n++; - } - lp = lp->prev; - } - if (!lp) { - raise_error(s, msg); - } - else { - if (n > 0) { - genop_1(s, OP_POPERR, n); - } - if (s->ensure_level > lp->ensure_level) { - genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level); - } - genjmp(s, OP_JMP, lp->pc0); - } + genjmp(s, OP_JMPUW, lp->pc0); } if (val) push(); } @@ -2264,26 +2461,25 @@ codegen(codegen_scope *s, node *tree, int val) if (idx > 0) { gen_move(s, cursp(), idx, val); - if (val && on_eval(s)) genop_0(s, OP_NOP); } else { - int lv = 0; - codegen_scope *up = s->prev; - - while (up) { - idx = lv_idx(up, nsym(tree)); - if (idx > 0) { - genop_3(s, OP_GETUPVAR, cursp(), idx, lv); - break; - } - lv++; - up = up->prev; - } + int lv = search_upvar(s, nsym(tree), &idx); + genop_3(s, OP_GETUPVAR, cursp(), idx, lv); } push(); } break; + case NODE_NVAR: + if (val) { + int idx = nint(tree); + + gen_move(s, cursp(), idx, val); + + push(); + } + break; + case NODE_GVAR: { int sym = new_sym(s, nsym(tree)); @@ -2320,19 +2516,11 @@ codegen(codegen_scope *s, node *tree, int val) } break; - case NODE_DEFINED: - codegen(s, tree, val); - break; - case NODE_BACK_REF: if (val) { - char buf[3]; - int sym; + char buf[] = {'$', nchar(tree)}; + int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf))); - buf[0] = '$'; - buf[1] = nchar(tree); - buf[2] = 0; - sym = new_sym(s, mrb_intern_cstr(s->mrb, buf)); genop_2(s, OP_GETGV, cursp(), sym); push(); } @@ -2344,7 +2532,7 @@ codegen(codegen_scope *s, node *tree, int val) mrb_value str; int sym; - str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree))); + str = mrb_format(mrb, "$%d", nint(tree)); sym = new_sym(s, mrb_intern_str(mrb, str)); genop_2(s, OP_GETGV, cursp(), sym); push(); @@ -2366,23 +2554,27 @@ codegen(codegen_scope *s, node *tree, int val) mrb_int i; mrb_bool overflow; - i = readint_mrb_int(s, p, base, FALSE, &overflow); -#ifndef MRB_WITHOUT_FLOAT + i = readint(s, p, base, &overflow); if (overflow) { - double f = readint_float(s, p, base); - int off = new_lit(s, mrb_float_value(s->mrb, f)); - + int off = new_litbn(s, p, base, FALSE); genop_2(s, OP_LOADL, cursp(), off); } - else -#endif - { - if (i == -1) genop_1(s, OP_LOADI__1, cursp()); - else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i); + else { + if (i < 0) { + if (i == -1) genop_1(s, OP_LOADI__1, cursp()); + else if (i >= -0xff) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i); + else if (i >= INT16_MIN) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i); + else if (i >= INT32_MIN) genop_2SS(s, OP_LOADI32, cursp(), (uint32_t)i); + else goto lit_int; + } else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp()); - else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i); + else if (i <= 0xff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i); + else if (i <= INT16_MAX) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i); + else if (i <= INT32_MAX) genop_2SS(s, OP_LOADI32, cursp(), (uint32_t)i); else { - int off = new_lit(s, mrb_fixnum_value(i)); + int off; + lit_int: + off = new_lit(s, mrb_int_value(s->mrb, i)); genop_2(s, OP_LOADL, cursp(), off); } } @@ -2390,7 +2582,7 @@ codegen(codegen_scope *s, node *tree, int val) } break; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case NODE_FLOAT: if (val) { char *p = (char*)tree; @@ -2407,7 +2599,7 @@ codegen(codegen_scope *s, node *tree, int val) { nt = nint(tree->car); switch (nt) { -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT case NODE_FLOAT: if (val) { char *p = (char*)tree->cdr; @@ -2427,34 +2619,35 @@ codegen(codegen_scope *s, node *tree, int val) mrb_int i; mrb_bool overflow; - i = readint_mrb_int(s, p, base, TRUE, &overflow); -#ifndef MRB_WITHOUT_FLOAT + i = readint(s, p, base, &overflow); if (overflow) { - double f = readint_float(s, p, base); - int off = new_lit(s, mrb_float_value(s->mrb, -f)); - + int off = new_litbn(s, p, base, TRUE); genop_2(s, OP_LOADL, cursp(), off); } else { -#endif + i = -i; if (i == -1) genop_1(s, OP_LOADI__1, cursp()); - else if (i >= -0xffff) { + else if (i >= -0xff) { genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i); } + else if (i >= INT16_MIN) { + genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i); + } + else if (i >= INT32_MIN) { + genop_2SS(s, OP_LOADI32, cursp(), (uint32_t)i); + } else { - int off = new_lit(s, mrb_fixnum_value(i)); + int off = new_lit(s, mrb_int_value(s->mrb, i)); genop_2(s, OP_LOADL, cursp(), off); } -#ifndef MRB_WITHOUT_FLOAT } -#endif push(); } break; default: if (val) { - int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@")); + int sym = new_sym(s, MRB_OPSYM_2(s->mrb, minus)); codegen(s, tree, VAL); pop(); genop_3(s, OP_SEND, cursp(), sym, 0); @@ -2527,7 +2720,7 @@ codegen(codegen_scope *s, node *tree, int val) { node *n; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); + int sym = new_sym(s, MRB_SYM_2(s->mrb, Kernel)); genop_1(s, OP_LOADSELF, cursp()); push(); @@ -2546,7 +2739,7 @@ codegen(codegen_scope *s, node *tree, int val) } push(); /* for block */ pop_n(3); - sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); + sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */ genop_3(s, OP_SEND, cursp(), sym, 1); if (val) push(); mrb_gc_arena_restore(s->mrb, ai); @@ -2566,7 +2759,7 @@ codegen(codegen_scope *s, node *tree, int val) genop_2(s, OP_STRING, cursp(), off); push(); push(); pop_n(3); - sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); + sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */ genop_3(s, OP_SEND, cursp(), sym, 1); if (val) push(); mrb_gc_arena_restore(s->mrb, ai); @@ -2607,7 +2800,7 @@ codegen(codegen_scope *s, node *tree, int val) } push(); /* space for a block */ pop_n(argc+2); - sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); + sym = new_sym(s, MRB_SYM_2(s->mrb, compile)); genop_3(s, OP_SEND, cursp(), sym, argc); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2661,7 +2854,7 @@ codegen(codegen_scope *s, node *tree, int val) } push(); /* space for a block */ pop_n(argc+2); - sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); + sym = new_sym(s, MRB_SYM_2(s->mrb, compile)); genop_3(s, OP_SEND, cursp(), sym, argc); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2778,7 +2971,10 @@ codegen(codegen_scope *s, node *tree, int val) idx = new_sym(s, nsym(tree->car->cdr)); genop_2(s, OP_CLASS, cursp(), idx); body = tree->cdr->cdr->car; - if (!(nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL)) { + if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) { + genop_1(s, OP_LOADNIL, cursp()); + } + else { idx = scope_body(s, body, val); genop_2(s, OP_EXEC, cursp(), idx); } @@ -2806,8 +3002,11 @@ codegen(codegen_scope *s, node *tree, int val) pop(); idx = new_sym(s, nsym(tree->car->cdr)); genop_2(s, OP_MODULE, cursp(), idx); - if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN && - tree->cdr->car->cdr->cdr == NULL)) { + if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN && + tree->cdr->car->cdr->cdr == NULL) { + genop_1(s, OP_LOADNIL, cursp()); + } + else { idx = scope_body(s, tree->cdr->car, val); genop_2(s, OP_EXEC, cursp(), idx); } @@ -2824,8 +3023,11 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); genop_1(s, OP_SCLASS, cursp()); - if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN && - tree->cdr->car->cdr->cdr == NULL)) { + if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN && + tree->cdr->car->cdr->cdr == NULL) { + genop_1(s, OP_LOADNIL, cursp()); + } + else { idx = scope_body(s, tree->cdr->car, val); genop_2(s, OP_EXEC, cursp(), idx); } @@ -2846,10 +3048,7 @@ codegen(codegen_scope *s, node *tree, int val) push(); pop(); pop(); genop_2(s, OP_DEF, cursp(), sym); - if (val) { - genop_2(s, OP_LOADSYM, cursp(), sym); - push(); - } + if (val) push(); } break; @@ -2866,10 +3065,7 @@ codegen(codegen_scope *s, node *tree, int val) genop_2(s, OP_METHOD, cursp(), idx); pop(); genop_2(s, OP_DEF, cursp(), sym); - if (val) { - genop_2(s, OP_LOADSYM, cursp(), sym); - push(); - } + if (val) push(); } break; @@ -2885,97 +3081,100 @@ codegen(codegen_scope *s, node *tree, int val) } static void -scope_add_irep(codegen_scope *s, mrb_irep *irep) +scope_add_irep(codegen_scope *s) { - if (s->irep == NULL) { - s->irep = irep; + mrb_irep *irep; + codegen_scope *prev = s->prev; + + if (prev->irep == NULL) { + irep = mrb_add_irep(s->mrb); + prev->irep = s->irep = irep; return; } - if (s->irep->rlen == s->rcapa) { - s->rcapa *= 2; - s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa); + else { + if (prev->irep->rlen == UINT16_MAX) { + codegen_error(s, "too many nested blocks/methods"); + } + s->irep = irep = mrb_add_irep(s->mrb); + if (prev->irep->rlen == prev->rcapa) { + prev->rcapa *= 2; + prev->reps = (mrb_irep**)codegen_realloc(s, prev->reps, sizeof(mrb_irep*)*prev->rcapa); + } + prev->reps[prev->irep->rlen] = irep; + prev->irep->rlen++; } - s->irep->reps[s->irep->rlen] = irep; - s->irep->rlen++; } static codegen_scope* -scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) +scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv) { static const codegen_scope codegen_scope_zero = { 0 }; mrb_pool *pool = mrb_pool_open(mrb); - codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope)); - - if (!p) return NULL; - *p = codegen_scope_zero; - p->mrb = mrb; - p->mpool = pool; - if (!prev) return p; - p->prev = prev; - p->ainfo = -1; - p->mscope = 0; - - p->irep = mrb_add_irep(mrb); - scope_add_irep(prev, p->irep); - - p->rcapa = 8; - p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa); - - p->icapa = 1024; - p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); - p->irep->iseq = NULL; - - p->pcapa = 32; - p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); - p->irep->plen = 0; - - p->scapa = 256; - p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); - p->irep->slen = 0; - - p->lv = lv; - p->sp += node_len(lv)+1; /* add self */ - p->nlocals = p->sp; - if (lv) { - node *n = lv; + codegen_scope *s = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope)); + + if (!s) { + if (prev) + codegen_error(prev, "unexpected scope"); + return NULL; + } + *s = codegen_scope_zero; + s->mrb = mrb; + s->mpool = pool; + if (!prev) return s; + s->prev = prev; + s->ainfo = -1; + s->mscope = 0; + + scope_add_irep(s); + + s->rcapa = 8; + s->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*s->rcapa); + + s->icapa = 1024; + s->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*s->icapa); + + s->pcapa = 32; + s->pool = (mrb_pool_value*)mrb_malloc(mrb, sizeof(mrb_pool_value)*s->pcapa); + + s->scapa = 256; + s->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*s->scapa); + + s->lv = nlv; + s->sp += node_len(nlv)+1; /* add self */ + s->nlocals = s->sp; + if (nlv) { + mrb_sym *lv; + node *n = nlv; size_t i = 0; - p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1)); - for (i=0, n=lv; n; i++,n=n->cdr) { - p->irep->lv[i].name = lv_name(n); - if (lv_name(n)) { - p->irep->lv[i].r = lv_idx(p, lv_name(n)); - } - else { - p->irep->lv[i].r = 0; - } + s->irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*(s->nlocals-1)); + for (i=0, n=nlv; n; i++,n=n->cdr) { + lv[i] = lv_name(n); } - mrb_assert(i + 1 == p->nlocals); + mrb_assert(i + 1 == s->nlocals); } - p->ai = mrb_gc_arena_save(mrb); + s->ai = mrb_gc_arena_save(mrb); - p->filename = prev->filename; - if (p->filename) { - p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa); + s->filename_sym = prev->filename_sym; + if (s->filename_sym) { + s->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*s->icapa); } - p->lineno = prev->lineno; + s->lineno = prev->lineno; /* debug setting */ - p->debug_start_pos = 0; - if (p->filename) { - mrb_debug_info_alloc(mrb, p->irep); - p->irep->filename = p->filename; - p->irep->lines = p->lines; + s->debug_start_pos = 0; + if (s->filename_sym) { + mrb_debug_info_alloc(mrb, s->irep); } else { - p->irep->debug_info = NULL; + s->irep->debug_info = NULL; } - p->parser = prev->parser; - p->filename_index = prev->filename_index; + s->parser = prev->parser; + s->filename_index = prev->filename_index; - p->rlev = prev->rlev+1; + s->rlev = prev->rlev+1; - return p; + return s; } static void @@ -2983,34 +3182,35 @@ scope_finish(codegen_scope *s) { mrb_state *mrb = s->mrb; mrb_irep *irep = s->irep; - size_t fname_len; - char *fname; + if (s->nlocals > 0xff) { + codegen_error(s, "too many local variables"); + } irep->flags = 0; if (s->iseq) { - irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); + size_t catchsize = sizeof(struct mrb_irep_catch_handler) * irep->clen; + irep->iseq = (const mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc + catchsize); irep->ilen = s->pc; - if (s->lines) { - irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc); - } - else { - irep->lines = 0; + if (irep->clen > 0) { + memcpy((void *)(irep->iseq + irep->ilen), s->catch_table, catchsize); } } - irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen); - irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen); - irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen); - if (s->filename) { - irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); - mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc); + else { + irep->clen = 0; + } + mrb_free(s->mrb, s->catch_table); + s->catch_table = NULL; + irep->pool = (const mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*irep->plen); + irep->syms = (const mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*irep->slen); + irep->reps = (const mrb_irep**)codegen_realloc(s, s->reps, sizeof(mrb_irep*)*irep->rlen); + if (s->filename_sym) { + mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index); + const char *filename = mrb_sym_name_len(s->mrb, fname, NULL); - fname_len = strlen(s->filename); - fname = (char*)codegen_malloc(s, fname_len + 1); - memcpy(fname, s->filename, fname_len); - fname[fname_len] = '\0'; - irep->filename = fname; - irep->own_filename = TRUE; + mrb_debug_info_append_file(s->mrb, s->irep->debug_info, + filename, s->lines, s->debug_start_pos, s->pc); } + mrb_free(s->mrb, s->lines); irep->nlocals = s->nlocals; irep->nregs = s->nregs; @@ -3025,9 +3225,8 @@ loop_push(codegen_scope *s, enum looptype t) struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo)); p->type = t; - p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0; + p->pc0 = p->pc1 = p->pc2 = p->pc3 = JMPLINK_START; p->prev = s->loop; - p->ensure_level = s->ensure_level; p->acc = cursp(); s->loop = p; @@ -3043,7 +3242,6 @@ loop_break(codegen_scope *s, node *tree) } else { struct loopinfo *loop; - int n = 0; if (tree) { gen_retval(s, tree); @@ -3052,7 +3250,6 @@ loop_break(codegen_scope *s, node *tree) loop = s->loop; while (loop) { if (loop->type == LOOP_BEGIN) { - n++; loop = loop->prev; } else if (loop->type == LOOP_RESCUE) { @@ -3066,20 +3263,14 @@ loop_break(codegen_scope *s, node *tree) raise_error(s, "unexpected break"); return; } - if (n > 0) { - genop_1(s, OP_POPERR, n); - } if (loop->type == LOOP_NORMAL) { int tmp; - if (s->ensure_level > s->loop->ensure_level) { - genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level); - } if (tree) { gen_move(s, loop->acc, cursp(), 0); } - tmp = genjmp(s, OP_JMP, loop->pc3); + tmp = genjmp(s, OP_JMPUW, loop->pc3); loop->pc3 = tmp; } else { @@ -3102,6 +3293,28 @@ loop_pop(codegen_scope *s, int val) if (val) push(); } +static int +catch_handler_new(codegen_scope *s) +{ + size_t newsize = sizeof(struct mrb_irep_catch_handler) * (s->irep->clen + 1); + s->catch_table = (struct mrb_irep_catch_handler *)codegen_realloc(s, (void *)s->catch_table, newsize); + return s->irep->clen ++; +} + +static void +catch_handler_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target) +{ + struct mrb_irep_catch_handler *e; + + mrb_assert(ent >= 0 && ent < s->irep->clen); + + e = &s->catch_table[ent]; + uint8_to_bin(type, &e->type); + mrb_irep_catch_handler_pack(begin, e->begin); + mrb_irep_catch_handler_pack(end, e->end); + mrb_irep_catch_handler_pack(target, e->target); +} + static struct RProc* generate_code(mrb_state *mrb, parser_state *p, int val) { @@ -3109,12 +3322,9 @@ generate_code(mrb_state *mrb, parser_state *p, int val) struct RProc *proc; struct mrb_jmpbuf *prev_jmp = mrb->jmp; - if (!scope) { - return NULL; - } scope->mrb = mrb; scope->parser = p; - scope->filename = p->filename; + scope->filename_sym = p->filename_sym; scope->filename_index = p->current_filename_index; MRB_TRY(&scope->jmp) { @@ -3151,13 +3361,14 @@ mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep) { int i; + if (irep->flags & MRB_IREP_NO_FREE) return; if (irep->lv) { - mrb_free(mrb, irep->lv); + mrb_free(mrb, (void*)irep->lv); irep->lv = NULL; } - + if (!irep->reps) return; for (i = 0; i < irep->rlen; ++i) { - mrb_irep_remove_lv(mrb, irep->reps[i]); + mrb_irep_remove_lv(mrb, (mrb_irep*)irep->reps[i]); } } @@ -3165,21 +3376,20 @@ mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep) #define Z 1 #define S 3 #define W 4 +#define OPCODE(_,x) x, /* instruction sizes */ uint8_t mrb_insn_size[] = { #define B 2 #define BB 3 #define BBB 4 #define BS 4 -#define SB 4 -#define OPCODE(_,x) x, +#define BSS 6 #include "mruby/ops.h" -#undef OPCODE #undef B #undef BB -#undef BS -#undef SB #undef BBB +#undef BS +#undef BSS }; /* EXT1 instruction sizes */ uint8_t mrb_insn_size1[] = { @@ -3187,29 +3397,30 @@ uint8_t mrb_insn_size1[] = { #define BB 4 #define BBB 5 #define BS 5 -#define SB 5 -#define OPCODE(_,x) x, +#define BSS 7 #include "mruby/ops.h" -#undef OPCODE #undef B +#undef BS +#undef BSS }; /* EXT2 instruction sizes */ uint8_t mrb_insn_size2[] = { #define B 2 -#define OPCODE(_,x) x, +#define BS 4 +#define BSS 6 #include "mruby/ops.h" -#undef OPCODE +#undef B #undef BB #undef BBB #undef BS -#undef SB +#undef BSS }; /* EXT3 instruction sizes */ +#define B 3 #define BB 5 #define BBB 6 -#define BS 4 -#define SB 5 +#define BS 5 +#define BSS 7 uint8_t mrb_insn_size3[] = { -#define OPCODE(_,x) x, #include "mruby/ops.h" }; |
