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;
}