modules/mruby/src/codegen.c in webruby-0.2.2 vs modules/mruby/src/codegen.c in webruby-0.2.4

- old
+ new

@@ -7,11 +7,11 @@ #include <ctype.h> #include <stdlib.h> #include <string.h> #include "mruby.h" #include "mruby/compile.h" -#include "mruby/irep.h" +#include "mruby/proc.h" #include "mruby/numeric.h" #include "mruby/string.h" #include "mruby/debug.h" #include "node.h" #include "opcode.h" @@ -59,18 +59,17 @@ uint16_t *lines; int icapa; mrb_irep *irep; size_t pcapa; - int scapa; + size_t scapa; + size_t rcapa; int nlocals; int nregs; int ai; - int idx; - int debug_start_pos; uint16_t filename_index; parser_state* parser; } codegen_scope; @@ -88,14 +87,14 @@ static void codegen_error(codegen_scope *s, const char *message) { if (!s) return; while (s->prev) { + codegen_scope *tmp = s->prev; mrb_pool_close(s->mpool); - s = s->prev; + s = tmp; } - mrb_pool_close(s->mpool); #ifdef ENABLE_STDIO if (s->filename && s->lineno) { fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); } else { @@ -112,23 +111,23 @@ if (!p) codegen_error(s, "pool memory allocation"); return p; } -void* +static void* codegen_malloc(codegen_scope *s, size_t len) { - void *p = mrb_malloc(s->mrb, len); + void *p = mrb_malloc_simple(s->mrb, len); if (!p) codegen_error(s, "mrb_malloc"); return p; } -void* +static void* codegen_realloc(codegen_scope *s, void *p, size_t len) { - p = mrb_realloc(s->mrb, p, len); + p = mrb_realloc_simple(s->mrb, p, len); if (!p && len > 0) codegen_error(s, "mrb_realloc"); return p; } @@ -396,38 +395,69 @@ static inline int new_lit(codegen_scope *s, mrb_value val) { size_t i; + mrb_value *pv; switch (mrb_type(val)) { case MRB_TT_STRING: for (i=0; i<s->irep->plen; i++) { - mrb_value pv = s->irep->pool[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) + 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) return i; } break; case MRB_TT_FLOAT: - default: for (i=0; i<s->irep->plen; i++) { - if (mrb_obj_equal(s->mrb, s->irep->pool[i], val)) return i; + pv = &s->irep->pool[i]; + if (mrb_type(*pv) != MRB_TT_FLOAT) continue; + if (mrb_float(*pv) == mrb_float(val)) return i; } break; + case MRB_TT_FIXNUM: + for (i=0; i<s->irep->plen; i++) { + pv = &s->irep->pool[i]; + if (mrb_type(*pv) != MRB_TT_FIXNUM) continue; + if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i; + } + break; + default: + /* should not happen */ + return 0; } 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->irep->pool[s->irep->plen] = val; + + pv = &s->irep->pool[s->irep->plen]; i = s->irep->plen++; + switch (mrb_type(val)) { + case MRB_TT_STRING: + *pv = mrb_str_pool(s->mrb, val); + break; + + case MRB_TT_FLOAT: +#ifdef MRB_WORD_BOXING + *pv = mrb_float_pool(s->mrb, mrb_float(val)); + break; +#endif + case MRB_TT_FIXNUM: + *pv = val; + break; + + default: + /* should not happen */ + break; + } return i; } static inline int new_msym(codegen_scope *s, mrb_sym sym) @@ -498,20 +528,19 @@ static void for_body(codegen_scope *s, node *tree) { codegen_scope *prev = s; - int idx, base = s->idx; + int idx; struct loopinfo *lp; node *n2; mrb_code c; // generate receiver codegen(s, tree->cdr->car, VAL); // generate loop-block s = scope_new(s->mrb, s, tree->car); - idx = s->idx; lp = loop_push(s, LOOP_FOR); lp->pc1 = new_label(s); // generate loop variable @@ -532,24 +561,22 @@ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); } loop_pop(s, NOVAL); scope_finish(s); s = prev; - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK)); + genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK)); pop(); - idx = new_msym(s, mrb_intern2(s->mrb, "each", 4)); + idx = new_msym(s, mrb_intern_lit(s->mrb, "each")); genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); } static int lambda_body(codegen_scope *s, node *tree, int blk) { - int idx, base = s->idx; mrb_code c; - + codegen_scope *parent = s; s = scope_new(s->mrb, s, tree->car); - idx = s->idx; s->mscope = !blk; if (blk) { struct loopinfo *lp = loop_push(s, LOOP_BLOCK); lp->pc1 = new_label(s); @@ -624,19 +651,17 @@ } if (blk) { loop_pop(s, NOVAL); } scope_finish(s); - - return idx - base; + return parent->irep->rlen - 1; } static int scope_body(codegen_scope *s, node *tree) { codegen_scope *scope = scope_new(s->mrb, s, tree->car); - int idx = scope->idx; codegen(scope, tree->cdr, VAL); if (!s->iseq) { genop(scope, MKOP_A(OP_STOP, 0)); } @@ -644,16 +669,21 @@ if (scope->nregs == 0) { genop(scope, MKOP_A(OP_LOADNIL, 0)); genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); } else { - genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL), NOVAL); + pop(); + genop_peep(scope, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); + push(); } } scope_finish(scope); - - return idx - s->idx; + if (!s->irep) { + /* should not happen */ + return 0; + } + return s->irep->rlen - 1; } static mrb_bool nosplat(node *t) { @@ -675,11 +705,11 @@ name2 = (char *)codegen_palloc(s, len+1); memcpy(name2, name, len); name2[len] = '='; name2[len+1] = '\0'; - return mrb_intern2(s->mrb, name2, len+1); + return mrb_intern(s->mrb, name2, len+1); } static int gen_values(codegen_scope *s, node *t, int val) { @@ -944,11 +974,11 @@ static void gen_send_intern(codegen_scope *s) { pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0)); push(); } static void gen_literal_array(codegen_scope *s, node *tree, int sym, int val) { @@ -1144,16 +1174,16 @@ do { if (n4) { codegen(s, n4->car, VAL); } else { - genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13)))); + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError")))); push(); } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); tmp = new_label(s); genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); pos2 = tmp; if (n4) { n4 = n4->cdr; @@ -1353,11 +1383,11 @@ while (n) { codegen(s, n->car, VAL); if (head) { genop(s, MKOP_AB(OP_MOVE, cursp(), head)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); } else { pop(); } tmp = new_label(s); @@ -1693,11 +1723,11 @@ push(); } } pop_n(n+1); if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n)); if (val) push(); } break; case NODE_BREAK: @@ -1963,11 +1993,11 @@ } break; default: { - int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1)); + int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); push(); codegen(s, tree, VAL); pop(); pop(); @@ -2031,19 +2061,19 @@ case NODE_XSTR: if (val) { char *p = (char*)tree->car; size_t len = (intptr_t)tree->cdr; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6)); + int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); int off = new_lit(s, mrb_str_new(s->mrb, p, len)); genop(s, MKOP_A(OP_OCLASS, cursp())); genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); push(); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "`", 1)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); mrb_gc_arena_restore(s->mrb, ai); push(); } break; @@ -2051,11 +2081,11 @@ case NODE_REGX: if (val) { char *p1 = (char*)tree->car; char *p2 = (char*)tree->cdr; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); + int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1))); int argc = 1; genop(s, MKOP_A(OP_OCLASS, cursp())); genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); @@ -2067,22 +2097,22 @@ genop(s, MKOP_ABx(OP_STRING, cursp(), off)); argc++; pop(); } pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); } break; case NODE_DREGX: if (val) { node *n = tree->car; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); + int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); int argc = 1; int off; char *p; genop(s, MKOP_A(OP_OCLASS, cursp())); @@ -2115,11 +2145,11 @@ genop(s, MKOP_ABx(OP_STRING, cursp(), off)); argc++; pop(); } pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); } else { @@ -2180,11 +2210,11 @@ case NODE_ALIAS: { int a = new_msym(s, sym(tree->car)); int b = new_msym(s, sym(tree->cdr)); - int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12)); + int c = new_msym(s, mrb_intern_lit(s->mrb,"alias_method")); genop(s, MKOP_A(OP_TCLASS, cursp())); push(); genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a)); push(); @@ -2199,11 +2229,11 @@ } break; case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12)); + int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method")); int num = 0; node *t = tree; genop(s, MKOP_A(OP_TCLASS, cursp())); push(); @@ -2340,10 +2370,25 @@ default: break; } } +static void +scope_add_irep(codegen_scope *s, mrb_irep *irep) +{ + if (s->irep == NULL) { + 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); + } + s->irep->reps[s->irep->rlen] = irep; + s->irep->rlen++; +} + static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) { static const codegen_scope codegen_scope_zero = { 0 }; mrb_pool *pool = mrb_pool_open(mrb); @@ -2357,21 +2402,25 @@ p->prev = prev; p->ainfo = -1; p->mscope = 0; p->irep = mrb_add_irep(mrb); - p->idx = p->irep->idx; + 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 = p->iseq; 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)*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; @@ -2416,12 +2465,13 @@ } else { irep->lines = 0; } } - 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->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) { s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc); fname_len = strlen(s->filename); @@ -2505,21 +2555,20 @@ s->loop = s->loop->prev; if (val) push(); } static void -codedump(mrb_state *mrb, int n) +codedump(mrb_state *mrb, mrb_irep *irep) { #ifdef ENABLE_STDIO - mrb_irep *irep = mrb->irep[n]; uint32_t i; int ai; mrb_code c; if (!irep) return; - printf("irep %d nregs=%d nlocals=%d pools=%d syms=%d\n", n, - irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen); + printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", irep, + irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen); for (i=0; i<irep->ilen; i++) { ai = mrb_gc_arena_save(mrb); printf("%03d ", i); c = irep->iseq[i]; switch (GET_OPCODE(c)) { @@ -2758,13 +2807,12 @@ case OP_APOST: printf("OP_APOST\tR%d\t%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c)); break; case OP_STRING: { - mrb_value s = irep->pool[GETARG_Bx(c)]; - - s = mrb_str_dump(mrb, s); + mrb_value v = irep->pool[GETARG_Bx(c)]; + mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s)); } break; case OP_STRCAT: printf("OP_STRCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c)); @@ -2783,11 +2831,11 @@ case OP_MODULE: printf("OP_MODULE\tR%d\t:%s\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_EXEC: - printf("OP_EXEC\tR%d\tI(%d)\n", GETARG_A(c), n+GETARG_Bx(c)); + printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c)); break; case OP_SCLASS: printf("OP_SCLASS\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c)); break; case OP_TCLASS: @@ -2795,11 +2843,11 @@ break; case OP_ERR: printf("OP_ERR\tL(%d)\n", GETARG_Bx(c)); break; case OP_EPUSH: - printf("OP_EPUSH\t:I(%d)\n", n+GETARG_Bx(c)); + printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)); break; case OP_ONERR: printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c)); break; case OP_RESCUE: @@ -2824,48 +2872,52 @@ } printf("\n"); #endif } -void -codedump_all(mrb_state *mrb, int start) +static void +codedump_recur(mrb_state *mrb, mrb_irep *irep) { size_t i; - for (i=start; i<mrb->irep_len; i++) { - codedump(mrb, i); + codedump(mrb, irep); + for (i=0; i<irep->rlen; i++) { + codedump_recur(mrb, irep->reps[i]); } } -static int -codegen_start(mrb_state *mrb, parser_state *p) + +void +codedump_all(mrb_state *mrb, struct RProc *proc) { + return codedump_recur(mrb, proc->body.irep); +} + +struct RProc* +mrb_generate_code(mrb_state *mrb, parser_state *p) +{ codegen_scope *scope = scope_new(mrb, 0, 0); + struct RProc *proc; if (!scope) { - return -1; + return NULL; } scope->mrb = mrb; scope->parser = p; scope->filename = p->filename; scope->filename_index = p->current_filename_index; if (setjmp(scope->jmp) == 0) { // prepare irep codegen(scope, p->tree, NOVAL); + proc = mrb_proc_new(mrb, scope->irep); + mrb_irep_decref(mrb, scope->irep); mrb_pool_close(scope->mpool); - return 0; + return proc; } else { - return -1; + if (scope->filename == scope->irep->filename) { + scope->irep->filename = NULL; + } + mrb_irep_decref(mrb, scope->irep); + mrb_pool_close(scope->mpool); + return NULL; } -} - -int -mrb_generate_code(mrb_state *mrb, parser_state *p) -{ - int start = mrb->irep_len; - int n; - - n = codegen_start(mrb, p); - if (n < 0) return n; - - return start; }