yarv-diff:318
From: ko1 atdot.net
Date: 7 Apr 2006 02:18:54 -0000
Subject: [yarv-diff:318] r483 - in trunk: . benchmark rb template
Author: ko1
Date: 2006-04-07 11:18:53 +0900 (Fri, 07 Apr 2006)
New Revision: 483
Modified:
trunk/
trunk/ChangeLog
trunk/benchmark/bmx_temp.rb
trunk/common.mk
trunk/compile.c
trunk/disasm.c
trunk/insns.def
trunk/rb/insns2vm.rb
trunk/rb/yasm.rb
trunk/template/insns.inc.tmpl
trunk/vm.c
trunk/vm_evalbody.h
trunk/yarvcore.c
trunk/yarvcore.h
Log:
r745@lermite: ko1 | 2006-04-07 11:15:28 +0900
* common.mk : fix some make rules
* insns.def : rename some instructions name
* rb/insns2vm.rb : change some operand type name
* vm_evalbody.h : ditto
* template/insns.inc.tmpl : add YARV_MAX_INSTRUCTION_SIZE macro
* compile.c, disasm.c, yarvcore.c : support load/store iseq from/to simple
data structure such as array, literals, and so on
* rb/yasm.rb : supported
* vm.c : change interface of eval_define_method
* yarvcore.h : remove unused externals
Property changes on: trunk
___________________________________________________________________
Name: svk:merge
- 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:740
+ 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:745
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/ChangeLog 2006-04-07 02:18:53 UTC (rev 483)
@@ -4,6 +4,28 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2006-04-07(Fri) 11:09:43 +0900 Koichi Sasada <ko1 atdot.net>
+
+ * common.mk : fix some make rules
+
+ * insns.def : rename some instructions name
+
+ * rb/insns2vm.rb : change some operand type name
+
+ * vm_evalbody.h : ditto
+
+ * template/insns.inc.tmpl : add YARV_MAX_INSTRUCTION_SIZE macro
+
+ * compile.c, disasm.c, yarvcore.c : support load/store iseq from/to simple
+ data structure such as array, literals, and so on
+
+ * rb/yasm.rb : supported
+
+ * vm.c : change interface of eval_define_method
+
+ * yarvcore.h : remove unused externals
+
+
2006-03-08(Wed) 10:31:29 +0900 Minero Aoki <aamine loveruby.net>
* lib/delegate.rb (DelegateClass): do not delegate #send and
Modified: trunk/benchmark/bmx_temp.rb
===================================================================
--- trunk/benchmark/bmx_temp.rb 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/benchmark/bmx_temp.rb 2006-04-07 02:18:53 UTC (rev 483)
@@ -1,7 +1,33 @@
-1000000.times{
+
+class Range
+ def each
+ f = self.first
+ l = self.last
+ while f < l
+ yield
+ f = f.succ
+ end
+ end
+end
+
+(0..10000000).each{
}
+
__END__
+class Fixnum_
+ def times
+ i = 0
+ while i<self
+ yield(i)
+ i+=1
+ end
+ end
+end
+10000000.times{
+}
+__END__
+
ths = (1..10).map{
Thread.new{
1000000.times{
Modified: trunk/common.mk
===================================================================
--- trunk/common.mk 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/common.mk 2006-04-07 02:18:53 UTC (rev 483)
@@ -440,10 +440,10 @@
$(MINIRUBY) $(srcdir)/rb/parse.rb $(srcdir)/test.rb
benchmark: all
- $(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb $(OPT) $(ITEMS) --yarv-program=./$(RUBY) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib
+ $(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb $(OPT) $(ITEMS) --yarv-program=./$(PROGRAM) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib
-tbench: all
- $(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb bmx $(OPT) --yarv-program=./$(RUBY) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib
+tbench: prog
+ $(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb bmx $(OPT) --yarv-program=./$(PROGRAM) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib
bench-each: all
$(BASERUBY) -I$(srcdir) $(srcdir)/benchmark/run_rite.rb bm_$(ITEM) $(OPT) --yarv-program=./$(RUBY) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib
Modified: trunk/compile.c
===================================================================
--- trunk/compile.c 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/compile.c 2006-04-07 02:18:53 UTC (rev 483)
@@ -223,7 +223,7 @@
/* wide range catch handler must put at last */
ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start);
- ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end);
+ ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, start, 0, end);
}
else if (iseq->type == ISEQ_TYPE_TOP) {
set_localtbl(iseq, GET_THREAD()->top_local_tbl);
@@ -259,7 +259,7 @@
ADD_INSN1(list_anchor, 0, throw, INT2FIX(0) /* continue throw */ );
}
else {
- ADD_INSN(list_anchor, iseq->compile_data->last_line, end);
+ ADD_INSN(list_anchor, iseq->compile_data->last_line, leave);
}
return iseq_setup(iseq, list_anchor);
@@ -730,8 +730,7 @@
static int
iseq_setup(yarv_iseq_t *iseq, LINK_ANCHOR *anchor)
{
-// debugs("[compile step 2] (iseq_array_to_linkedlist)\n");
-// iseq_array_to_linkedlist_each(anchor, seq_ary);
+ // debugs("[compile step 2] (iseq_array_to_linkedlist)\n");
GC_CHECK();
if (CPDEBUG > 5)
@@ -1316,7 +1315,7 @@
case TS_NUM: /* ulong */
generated_iseq[pos + 1 + j] = FIX2INT(operands[j]);
break;
- case TS_BLOCKISEQ: /* BLOCK */
+ case TS_ISEQ: /* iseq */
{
VALUE v = operands[j];
yarv_iseq_t *block = 0;
@@ -1546,8 +1545,8 @@
OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0);
continue;
}
- else if (diobj->insn_id == BIN(end)) {
- INSN *eiobj = new_insn_core(iseq, iobj->line_no, BIN(end),
+ else if (diobj->insn_id == BIN(leave)) {
+ INSN *eiobj = new_insn_core(iseq, iobj->line_no, BIN(leave),
diobj->operand_size,
diobj->operands);
/* replace */
@@ -1568,11 +1567,11 @@
* L2:
*/
else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&
- (piobj->insn_id == BIN(if) ||
- piobj->insn_id == BIN(unless))) {
+ (piobj->insn_id == BIN(branchif) ||
+ piobj->insn_id == BIN(branchunless))) {
if (niobj == (INSN *)get_destination_insn(piobj)) {
- piobj->insn_id = (piobj->insn_id == BIN(if))
- ? BIN(unless) : BIN(if) ;
+ piobj->insn_id = (piobj->insn_id == BIN(branchif))
+ ? BIN(branchunless) : BIN(branchif) ;
OPERAND_AT(piobj, 0) = OPERAND_AT(iobj, 0);
REMOVE_ELEM(&iobj->link);
}
@@ -1582,7 +1581,8 @@
dump_disasm_anchor(anchor);
}
}
- if (iobj->insn_id == BIN(if) || iobj->insn_id == BIN(unless)) {
+ if (iobj->insn_id == BIN(branchif) ||
+ iobj->insn_id == BIN(branchunless)) {
/*
* if L1
* ...
@@ -1597,7 +1597,7 @@
}
}
- if (iobj->insn_id == BIN(end)) {
+ if (iobj->insn_id == BIN(leave)) {
INSN *piobj = (INSN *)get_prev_insn((INSN *)list);
if (piobj->insn_id == BIN(send)) {
/* TODO: tail call optimization */
@@ -1740,7 +1740,7 @@
nstate = SCS_XX;
}
}
- else if (insn_id == BIN(end)) {
+ else if (insn_id == BIN(leave)) {
nstate = SCS_XX;
}
@@ -1926,7 +1926,7 @@
break;
default:
COMPILE(ret, "branch condition", cond);
- ADD_INSNL(ret, nd_line(cond), unless, else_label);
+ ADD_INSNL(ret, nd_line(cond), branchunless, else_label);
ADD_INSNL(ret, nd_line(cond), jump, then_label);
break;
}
@@ -2248,7 +2248,7 @@
LABEL *lcont = NEW_LABEL(nd_line(node));
defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
- ADD_INSNL(ret, nd_line(node), if, lcont) ;
+ ADD_INSNL(ret, nd_line(node), branchif, lcont) ;
ADD_INSN(ret, nd_line(node), putnil);
ADD_INSNL(ret, nd_line(node), jump, lfinish);
@@ -2261,7 +2261,7 @@
LABEL *lcont = NEW_LABEL(nd_line(node));
defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
- ADD_INSNL(ret, nd_line(node), if, lcont) ;
+ ADD_INSNL(ret, nd_line(node), branchif, lcont) ;
ADD_INSN(ret, nd_line(node), putnil);
ADD_INSNL(ret, nd_line(node), jump, lfinish);
@@ -2285,7 +2285,7 @@
LABEL *lcont = NEW_LABEL(nd_line(node));
defined_expr(iseq, ret, node->nd_recv, lfinish, Qfalse);
- ADD_INSNL(ret, nd_line(node), if, lcont) ;
+ ADD_INSNL(ret, nd_line(node), branchif, lcont) ;
ADD_INSN(ret, nd_line(node), putnil);
ADD_INSNL(ret, nd_line(node), jump, lfinish);
@@ -2335,7 +2335,7 @@
ADD_LABEL(ret, lstart);
COMPILE(ret, "defined expr (others)", node);
- ADD_INSNL(ret, nd_line(node), if, ldefed) ;
+ ADD_INSNL(ret, nd_line(node), branchif, ldefed) ;
ADD_INSN(ret, nd_line(node), putnil);
ADD_INSNL(ret, nd_line(node), jump, lend);
ADD_LABEL(ret, ldefed);
@@ -2596,7 +2596,7 @@
ADD_SEND(cond_seq, nd_line(node), ID2SYM(idEqq),
INT2FIX(1));
}
- ADD_INSNL(cond_seq, nd_line(node), if, l1) ;
+ ADD_INSNL(cond_seq, nd_line(node), branchif, l1) ;
vals = vals->nd_next;
}
}
@@ -2666,11 +2666,11 @@
ADD_INSN1(ret, nd_line(val), checkincludearray,
Qfalse);
ADD_INSN(ret, nd_line(val), pop);
- ADD_INSNL(ret, nd_line(val), if, l1) ;
+ ADD_INSNL(ret, nd_line(val), branchif, l1) ;
}
else {
COMPILE(ret, "when2", val);
- ADD_INSNL(ret, nd_line(val), if, l1) ;
+ ADD_INSNL(ret, nd_line(val), branchif, l1) ;
}
vals = vals->nd_next;
}
@@ -2728,7 +2728,7 @@
else {
ADD_INSN(ret, nd_line(node), putself);
ADD_CALL(ret, nd_line(node), ID2SYM(idGets), INT2FIX(0));
- ADD_INSNL(ret, nd_line(node), if, redo_label) ;
+ ADD_INSNL(ret, nd_line(node), branchif, redo_label) ;
/* opt_n */
}
@@ -2986,7 +2986,7 @@
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
INT2FIX(0));
ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
- ADD_INSNL(ret, nd_line(node), if, label_hit) ;
+ ADD_INSNL(ret, nd_line(node), branchif, label_hit) ;
narg = narg->nd_next;
}
if (resq->nd_args == 0) {
@@ -2995,12 +2995,12 @@
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
INT2FIX(0));
ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
- ADD_INSNL(ret, nd_line(node), if, label_hit) ;
+ ADD_INSNL(ret, nd_line(node), branchif, label_hit) ;
}
ADD_INSNL(ret, nd_line(node), jump, label_miss);
ADD_LABEL(ret, label_hit);
COMPILE(ret, "resbody body", resq->nd_body);
- ADD_INSN(ret, nd_line(node), end);
+ ADD_INSN(ret, nd_line(node), leave);
ADD_LABEL(ret, label_miss);
resq = resq->nd_head;
}
@@ -3057,10 +3057,10 @@
ADD_INSN(ret, nd_line(node), dup);
}
if (type == NODE_AND) {
- ADD_INSNL(ret, nd_line(node), unless, end_label);
+ ADD_INSNL(ret, nd_line(node), branchunless, end_label);
}
else {
- ADD_INSNL(ret, nd_line(node), if, end_label) ;
+ ADD_INSNL(ret, nd_line(node), branchif, end_label) ;
}
if (!poped) {
ADD_INSN(ret, nd_line(node), pop);
@@ -3221,12 +3221,12 @@
if (id == 0) {
/* or */
ADD_INSN(ret, nd_line(node), dup);
- ADD_INSNL(ret, nd_line(node), if, label) ;
+ ADD_INSNL(ret, nd_line(node), branchif, label) ;
ADD_INSN(ret, nd_line(node), pop);
}
else {
/* and */
- ADD_INSNL(ret, nd_line(node), unless, label);
+ ADD_INSNL(ret, nd_line(node), branchunless, label);
}
COMPILE(ret, "NODE_OP_ASGN1 args->head: ",
@@ -3312,10 +3312,10 @@
if (atype == 0 || atype == 1) { /* 0: OR or 1: AND */
ADD_INSN(ret, nd_line(node), dup);
if (atype == 0) {
- ADD_INSNL(ret, nd_line(node), if, lcfin) ;
+ ADD_INSNL(ret, nd_line(node), branchif, lcfin) ;
}
else {
- ADD_INSNL(ret, nd_line(node), unless, lcfin);
+ ADD_INSNL(ret, nd_line(node), branchunless, lcfin);
}
ADD_INSN(ret, nd_line(node), pop);
COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
@@ -3350,17 +3350,17 @@
if (nd_type(node) == NODE_OP_ASGN_OR) {
defined_expr(iseq, ret, node->nd_head, lassign, Qfalse);
- ADD_INSNL(ret, nd_line(node), unless, lassign);
+ ADD_INSNL(ret, nd_line(node), branchunless, lassign);
}
COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
ADD_INSN(ret, nd_line(node), dup);
if (nd_type(node) == NODE_OP_ASGN_AND) {
- ADD_INSNL(ret, nd_line(node), unless, lfin);
+ ADD_INSNL(ret, nd_line(node), branchunless, lfin);
}
else {
- ADD_INSNL(ret, nd_line(node), if, lfin) ;
+ ADD_INSNL(ret, nd_line(node), branchif, lfin) ;
}
ADD_INSN(ret, nd_line(node), pop);
@@ -3606,7 +3606,7 @@
}
}
- ADD_INSN3(ret, nd_line(node), super, argc, block, INT2FIX(flag));
+ ADD_INSN3(ret, nd_line(node), invokesuper, argc, block, INT2FIX(flag));
if (poped) {
ADD_INSN(ret, nd_line(node), pop);
@@ -3684,7 +3684,7 @@
if (is->type == ISEQ_TYPE_METHOD) {
add_ensure_iseq(ret, iseq);
- ADD_INSN(ret, nd_line(node), end);
+ ADD_INSN(ret, nd_line(node), leave);
}
else {
ADD_INSN1(ret, nd_line(node), throw,
@@ -3753,7 +3753,7 @@
argc = 0;
}
ADD_SEQ(ret, args);
- ADD_INSN2(ret, nd_line(node), yield, INT2FIX(argc),
+ ADD_INSN2(ret, nd_line(node), invokeblock, INT2FIX(argc),
INT2FIX(flag));
if (poped) {
@@ -4094,8 +4094,8 @@
ISEQ_TYPE_CLASS);
compile_cpath(ret, iseq, node->nd_cpath);
COMPILE(ret, "super", node->nd_super);
- ADD_INSN2(ret, nd_line(node), classdef,
- ID2SYM(node->nd_cpath->nd_mid), iseqval);
+ ADD_INSN3(ret, nd_line(node), defineclass,
+ ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(0));
if (poped) {
ADD_INSN(ret, nd_line(node), pop);
@@ -4111,8 +4111,9 @@
ISEQ_TYPE_CLASS);
COMPILE(ret, "mbase", node->nd_cpath->nd_head);
- ADD_INSN2(ret, nd_line(node), moduledef,
- ID2SYM(node->nd_cpath->nd_mid), iseqval);
+ ADD_INSN (ret, nd_line(node), putnil); /* dummy */
+ ADD_INSN3(ret, nd_line(node), defineclass,
+ ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(2));
if (poped) {
ADD_INSN(ret, nd_line(node), pop);
}
@@ -4124,7 +4125,9 @@
ISEQ_TYPE_CLASS);
COMPILE(ret, "sclass#recv", node->nd_recv);
- ADD_INSN1(ret, nd_line(node), singletonclassdef, iseqval);
+ ADD_INSN (ret, nd_line(node), putnil);
+ ADD_INSN3(ret, nd_line(node), defineclass,
+ ID2SYM(rb_intern("singletonclass")), iseqval, INT2FIX(1));
if (poped) {
ADD_INSN(ret, nd_line(node), pop);
@@ -4212,12 +4215,12 @@
ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(node->nd_cnt),
INT2FIX(0));
- ADD_INSNL(ret, nd_line(node), if, lend) ;
+ ADD_INSNL(ret, nd_line(node), branchif, lend) ;
/* *flip == 0 */
COMPILE(ret, "flip2 beg", node->nd_beg);
ADD_INSN(ret, nd_line(node), dup);
- ADD_INSNL(ret, nd_line(node), unless, lfin);
+ ADD_INSNL(ret, nd_line(node), branchunless, lfin);
if (nd_type(node) == NODE_FLIP3) {
ADD_INSN(ret, nd_line(node), dup);
ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt));
@@ -4230,7 +4233,7 @@
/* *flip == 1 */
ADD_LABEL(ret, lend);
COMPILE(ret, "flip2 end", node->nd_end);
- ADD_INSNL(ret, nd_line(node), unless, ltrue);
+ ADD_INSNL(ret, nd_line(node), branchunless, ltrue);
ADD_INSN1(ret, nd_line(node), putobject, Qfalse);
ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt));
@@ -4454,9 +4457,18 @@
break;
}
break;
+ case TS_ISEQ: /* iseq */
+ {
+ yarv_iseq_t *iseq = (yarv_iseq_t *)OPERAND_AT(insnobj, j);
+ VALUE val = Qnil;
+ if (iseq) {
+ val = iseq->self;
+ }
+ rb_str_concat(str, rb_inspect(val));
+ }
+ break;
case TS_LINDEX:
case TS_DINDEX:
- case TS_BLOCKISEQ: /* block */
case TS_NUM: /* ulong */
case TS_VALUE: /* VALUE */
rb_str_concat(str, rb_inspect(OPERAND_AT(insnobj, j)));
@@ -4549,3 +4561,148 @@
}
return ary;
}
+
+struct st_table *insn_make_insn_table(void);
+
+static int
+insn_simpledata2iseq_body(yarv_iseq_t *iseq, LINK_ANCHOR *anchor,
+ VALUE body, VALUE line)
+{
+ /* TODO: body should be freezed */
+ VALUE *ptr = RARRAY(body)->ptr;
+ int len = RARRAY(body)->len;
+ int i, j;
+ struct st_table *labels_table = st_init_numtable();
+ static struct st_table *insn_table;
+
+ if (insn_table == 0) {
+ insn_table = insn_make_insn_table();
+ }
+
+ for (i=0; i<len; i++) {
+ VALUE obj = ptr[i];
+
+ if (SYMBOL_P(obj)) {
+ LABEL *label = 0;
+ if (st_lookup(labels_table, obj, (st_data_t *)&label) == 0) {
+ label = NEW_LABEL(0);
+ st_insert(labels_table, obj, (st_data_t)label);
+ }
+ ADD_LABEL(anchor, label);
+ }
+ else if (TYPE(obj) == T_ARRAY) {
+ VALUE *argv = 0;
+ int argc = RARRAY(obj)->len - 1;
+ int line_no = 0;
+ VALUE insn_id;
+
+ if (st_lookup(insn_table, RARRAY(obj)->ptr[0], &insn_id) == 0) {
+ // TODO: exception
+ rb_bug("unknown instruction: ");
+ }
+
+ if (argc != insn_len(insn_id)-1) {
+ rb_bug("operand size mismatch");
+ }
+
+ if (argc > 0) {
+ argv = compile_data_alloc(iseq, sizeof(VALUE) * argc);
+ for (j=0; j<argc; j++) {
+ VALUE op = RARRAY(obj)->ptr[j+1];
+ switch (insn_op_type(insn_id, j)) {
+ case TS_OFFSET: {
+ LABEL *label;
+ if (st_lookup(labels_table, op, (st_data_t *)&label) == 0) {
+ label = NEW_LABEL(0);
+ st_insert(labels_table, op, (st_data_t)label);
+ }
+ argv[j] = (VALUE)label;
+ break;
+ }
+ case TS_LINDEX:
+ case TS_DINDEX:
+ case TS_NUM:
+ argv[j] = op;
+ break;
+ case TS_VALUE:
+ argv[j] = op;
+ if (!SPECIAL_CONST_P(op)) {
+ iseq_add_mark_object(iseq, op);
+ }
+ break;
+ case TS_ISEQ:
+ {
+ if (op != Qnil) {
+ argv[j] =
+ iseq_load_simpledata(0, op, iseq->self);
+ }
+ else {
+ argv[j] = 0;
+ }
+ }
+ break;
+ case TS_GENTRY:
+ argv[j] = (VALUE)rb_global_entry(SYM2ID(op));
+ break;
+ case TS_IC:
+ argv[j] = (VALUE)NEW_INLINE_CACHE_ENTRY();
+ iseq_add_mark_object(iseq, argv[j]);
+ break;
+ case TS_ID:
+ argv[j] = op;
+ break;
+ case TS_CDHASH:
+
+ default:
+ rb_bug("unknown operand: %c", insn_op_type(insn_id, j));
+ }
+ }
+ }
+ ADD_ELEM(anchor,
+ (LINK_ELEMENT*)new_insn_core(iseq, line_no,
+ insn_id, argc, argv));
+ }
+ else {
+ // TODO: should throw exception
+ rb_bug("unexpected object");
+ }
+ }
+ st_free_table(labels_table);
+ iseq_setup(iseq, anchor);
+ return COMPILE_OK;
+}
+
+VALUE
+iseq_simpledata2iseq(yarv_iseq_t *iseq, VALUE line,
+ VALUE args, VALUE vars, VALUE exception, VALUE body)
+{
+ int i;
+ int opt = 0;
+ ID *tbl;
+ DECL_ANCHOR(anchor);
+
+ if (iseq->type == ISEQ_TYPE_METHOD ||
+ iseq->type == ISEQ_TYPE_TOP ||
+ iseq->type == ISEQ_TYPE_CLASS) {
+ opt = 1;
+ }
+
+ iseq->local_size = opt + RARRAY(args)->len + RARRAY(vars)->len;
+ iseq->local_tbl = (ID *)ALLOC_N(ID *, iseq->local_size);
+ tbl = iseq->local_tbl + opt;
+
+ /* args */
+ for (i=0; i<RARRAY(args)->len; i++) {
+ *tbl++ = SYM2ID(RARRAY(args)->ptr[i]);
+ }
+ iseq->argc = i;
+
+ /* vars */
+ for (i=0; i<RARRAY(vars)->len; i++) {
+ *tbl++ = SYM2ID(RARRAY(vars)->ptr[i]);
+ }
+
+ /* body */
+ insn_simpledata2iseq_body(iseq, anchor, body, line);
+ return iseq->self;
+}
Modified: trunk/disasm.c
===================================================================
--- trunk/disasm.c 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/disasm.c 2006-04-07 02:18:53 UTC (rev 483)
@@ -70,11 +70,13 @@
snprintf(buff, sizeof(buff), "%lu", op);
ret = rb_str_new2(buff);
break;
- case TS_LINDEX:{
+
+ case TS_LINDEX:
+ {
yarv_iseq_t *ip = iseq->local_iseq;
ret =
- rb_str_new2(rb_id2name
- (ip->local_tbl[ip->local_size - op + 1]));
+ rb_str_new2(
+ rb_id2name(ip->local_tbl[ip->local_size - op + 1]));
break;
}
case TS_DINDEX:{
@@ -103,13 +105,13 @@
}
break;
- case TS_BLOCKISEQ: /* block */
+ case TS_ISEQ: /* iseq */
{
- yarv_iseq_t *block = (yarv_iseq_t *)op;
- if (block) {
- ret = block->name;
+ yarv_iseq_t *iseq = (yarv_iseq_t *)op;
+ if (iseq) {
+ ret = iseq->name;
if (child) {
- rb_ary_push(child, block->self);
+ rb_ary_push(child, iseq->self);
}
}
else {
@@ -565,4 +567,184 @@
printf("node name: %s\n", node_name(nd_type(node)));
printf("node filename: %s\n", node->nd_file);
return 0;
-}
\ No newline at end of file
+}
+
+#define DECL_SYMBOL(name) \
+ static VALUE sym_##name;
+#define INIT_SYMBOL(name) \
+ sym_##name = ID2SYM(rb_intern(#name))
+
+VALUE
+iseq_iseq2simpledata(yarv_iseq_t *iseq)
+{
+ int i, j, pos, opt = 0;
+ VALUE *seq;
+
+ VALUE val = rb_ary_new();
+ VALUE type; /* Symbol */
+ VALUE args = rb_ary_new(); /* [:arg1, ...] */
+ VALUE vars = rb_ary_new(); /* [:var1, ...] */
+ VALUE body = rb_ary_new(); /* [[:insn1, ...], ...] */
+ VALUE nbody;
+ VALUE line = rb_ary_new();
+ VALUE exception = rb_ary_new(); /* [[....]] */
+ static VALUE insn_syms[YARV_MAX_INSTRUCTION_SIZE];
+ struct st_table *labels_table = st_init_numtable();
+
+ DECL_SYMBOL(toplevel);
+ DECL_SYMBOL(method);
+ DECL_SYMBOL(block);
+ DECL_SYMBOL(class);
+ DECL_SYMBOL(rescue);
+ DECL_SYMBOL(ensure);
+ DECL_SYMBOL(eval);
+
+ if (sym_toplevel == 0) {
+ int i;
+ for (i=0; i<YARV_MAX_INSTRUCTION_SIZE; i++) {
+ insn_syms[i] = ID2SYM(rb_intern(insn_name(i)));
+ }
+ INIT_SYMBOL(toplevel);
+ INIT_SYMBOL(method);
+ INIT_SYMBOL(block);
+ INIT_SYMBOL(class);
+ INIT_SYMBOL(rescue);
+ INIT_SYMBOL(ensure);
+ INIT_SYMBOL(eval);
+ }
+
+ /* type */
+ switch(iseq->type) {
+ case ISEQ_TYPE_TOP: type = sym_toplevel; break;
+ case ISEQ_TYPE_METHOD: type = sym_method; break;
+ case ISEQ_TYPE_BLOCK: type = sym_block; break;
+ case ISEQ_TYPE_CLASS: type = sym_class; break;
+ case ISEQ_TYPE_RESCUE: type = sym_rescue; break;
+ case ISEQ_TYPE_ENSURE: type = sym_ensure; break;
+ case ISEQ_TYPE_EVAL: type = sym_eval; break;
+ default: rb_bug("unsupported iseq type");
+ };
+
+ if (iseq->type == ISEQ_TYPE_METHOD ||
+ iseq->type == ISEQ_TYPE_TOP ||
+ iseq->type == ISEQ_TYPE_CLASS) {
+ opt = 1;
+ }
+ /* args */
+ for (i=0; i<iseq->argc; i++) {
+ rb_ary_push(args, ID2SYM(iseq->local_tbl[i+opt]));
+ }
+ /* vars */
+ for(; i<iseq->local_size - opt; i++) {
+ rb_ary_push(vars, ID2SYM(iseq->local_tbl[i+opt]));
+ }
+
+ /* body */
+ for (seq = iseq->iseq; seq < iseq->iseq + iseq->size; ) {
+ VALUE ary = rb_ary_new();
+ VALUE insn = *seq++;
+ int j;
+ rb_ary_push(ary, insn_syms[insn]);
+ for (j=0; j<insn_len(insn)-1; j++, seq++) {
+ switch (insn_op_type(insn, j)) {
+ case TS_OFFSET: {
+ unsigned int idx = seq - iseq->iseq + *seq + 1;
+ char buff[0x20];
+ VALUE sym;
+ snprintf(buff, 0x20, "label_%u", idx);
+ sym = ID2SYM(rb_intern(buff));
+ rb_ary_push(ary, sym);
+ st_insert(labels_table, idx, sym);
+ break;
+ }
+ case TS_LINDEX:
+ case TS_DINDEX:
+ case TS_NUM:
+ rb_ary_push(ary, INT2FIX(*seq));
+ break;
+ case TS_VALUE:
+ rb_ary_push(ary, *seq);
+ break;
+ case TS_ISEQ:
+ {
+ yarv_iseq_t *iseq = (yarv_iseq_t *)*seq;
+ if (iseq) {
+ VALUE val = iseq_iseq2simpledata(iseq);
+ rb_ary_push(ary, val);
+ }
+ else {
+ rb_ary_push(ary, Qnil);
+ }
+ }
+ break;
+ case TS_GENTRY:
+ {
+ struct global_entry *entry = (struct global_entry *)*seq;
+ rb_ary_push(ary, ID2SYM(entry->id));
+ }
+ break;
+ case TS_IC:
+ rb_ary_push(ary, Qnil);
+ break;
+ case TS_ID:
+ rb_ary_push(ary, ID2SYM(*seq));
+ break;
+ case TS_CDHASH:
+ default:
+ rb_bug("unknown operand: %c", insn_op_type(insn, j));
+ }
+ }
+ rb_ary_push(body, ary);
+ }
+
+ nbody = body;
+ body = rb_ary_new();
+
+ for (i=0, pos=0; i<RARRAY(nbody)->len; i++) {
+ VALUE ary = RARRAY(nbody)->ptr[i];
+ VALUE label;
+
+ if (st_lookup(labels_table, pos, &label)) {
+ rb_ary_push(body, label);
+ }
+ rb_ary_push(body, ary);
+ pos += RARRAY(ary)->len;
+ }
+
+ st_free_table(labels_table);
+
+ /* build */
+
+ /* [magic, major_version, minor_version, format_type, misc,
+ * name, filename, line,
+ * type, args, vars, exception_table, body]
+ */
+ rb_ary_push(val, rb_str_new2("YARVInstructionSimpledataFormat"));
+ rb_ary_push(val, INT2FIX(1));
+ rb_ary_push(val, INT2FIX(1));
+ rb_ary_push(val, INT2FIX(1));
+ rb_ary_push(val, Qnil);
+ rb_ary_push(val, iseq->name);
+ rb_ary_push(val, iseq->file_name);
+ rb_ary_push(val, line);
+ rb_ary_push(val, type);
+ rb_ary_push(val, args);
+ rb_ary_push(val, vars);
+ rb_ary_push(val, exception);
+ rb_ary_push(val, body);
+ return val;
+}
+
+struct st_table *
+insn_make_insn_table(void)
+{
+ struct st_table *table;
+ table = st_init_numtable();
+ int i;
+
+ for (i=0; i<YARV_MAX_INSTRUCTION_SIZE; i++) {
+ st_insert(table, ID2SYM(rb_intern(insn_name(i))), i);
+ }
+
+ return table;
+}
Modified: trunk/insns.def
===================================================================
--- trunk/insns.def 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/insns.def 2006-04-07 02:18:53 UTC (rev 483)
@@ -800,7 +800,7 @@
*/
DEFINE_INSN
definemethod
-(ID id, VALUE body, num_t is_singleton)
+(ID id, ISEQ body, num_t is_singleton)
(VALUE obj)
()
{
@@ -960,7 +960,7 @@
*/
DEFINE_INSN
postexe
-(BLOCKISEQ blockiseq)
+(ISEQ blockiseq)
()
()
{
@@ -1007,51 +1007,82 @@
`A`BAklass NX`B
*/
DEFINE_INSN
-classdef
-(ID id, VALUE klass_iseqval)
+defineclass
+(ID id, ISEQ klass_iseq, num_t define_type)
(VALUE cbase, VALUE super)
(VALUE val)
{
- /* val is dummy. classdef returns class scope value */
- yarv_iseq_t *klass_iseq;
VALUE klass;
- if (super == Qnil) {
- super = rb_cObject;
- }
- if (cbase == Qnil) {
- cbase = th_get_cbase(th);
- }
+ if (define_type == 0) {
+ /* val is dummy. classdef returns class scope value */
- /* find klass */
- if (rb_const_defined_at(cbase, id)) {
- /* already exist */
- klass = rb_const_get_at(cbase, id);
- if (TYPE(klass) != T_CLASS) {
- rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id));
+ if (super == Qnil) {
+ super = rb_cObject;
}
+ if (cbase == Qnil) {
+ cbase = th_get_cbase(th);
+ }
- if (super != rb_cObject) {
- VALUE tmp;
- tmp = rb_class_real(RCLASS(klass)->super);
+ /* find klass */
+ if (rb_const_defined_at(cbase, id)) {
+ /* already exist */
+ klass = rb_const_get_at(cbase, id);
+ if (TYPE(klass) != T_CLASS) {
+ rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id));
+ }
- if (tmp != super) {
- rb_raise(rb_eTypeError, "superclass mismatch for class %s",
- rb_id2name(id));
+ if (super != rb_cObject) {
+ VALUE tmp;
+ tmp = rb_class_real(RCLASS(klass)->super);
+
+ if (tmp != super) {
+ rb_raise(rb_eTypeError, "superclass mismatch for class %s",
+ rb_id2name(id));
+ }
}
}
+ else {
+ /* new class declaration */
+ klass = rb_define_class_id(id, super);
+ rb_set_class_path(klass, cbase, rb_id2name(id));
+ rb_const_set(cbase, id, klass);
+ rb_class_inherited(super, klass);
+ }
}
- else {
- /* new class declaration */
- klass = rb_define_class_id(id, super);
- rb_set_class_path(klass, cbase, rb_id2name(id));
- rb_const_set(cbase, id, klass);
- rb_class_inherited(super, klass);
+ else if (define_type == 1) {
+ /* val is dummy. classdef returns class scope value */
+ /* super is dummy */
+ klass = rb_singleton_class(cbase);
}
+ else if (define_type == 2) {
+ /* val is dummy. classdef returns class scope value */
+ /* super is dummy */
+ if (cbase == Qnil) {
+ cbase = th_get_cbase(th);
+ }
- GetISeqVal(klass_iseqval, klass_iseq);
+ /* find klass */
+ if (rb_const_defined_at(cbase, id)) {
+ klass = rb_const_get_at(cbase, id);
+ /* already exist */
+ if (TYPE(klass) != T_MODULE) {
+ rb_raise(rb_eTypeError, "%s is not a module", rb_id2name(id));
+ }
+ }
+ else {
+ /* new module declaration */
+ klass = rb_define_module_id(id);
+ rb_set_class_path(klass, cbase, rb_id2name(id));
+ rb_const_set(cbase, id, klass);
+ }
+ }
+ else {
+ rb_bug("unknown defineclass type: %d", define_type);
+ }
+
COPY_CREF(klass_iseq->cref_stack, th_cref_push(th, klass, NOEX_PUBLIC));
-
+
/* enter scope */
push_frame(th, klass_iseq,
FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
@@ -1063,85 +1094,7 @@
NEXT_INSN();
}
-/**
- @c class/module
- @e enter singleton class definition scope.
- @j NX`XR[vsB
- */
-DEFINE_INSN
-singletonclassdef
-(VALUE sclass_iseqval)
-(VALUE obj)
-(VALUE val)
-{
- /* val is dummy. classdef returns class scope value */
- yarv_iseq_t *sklass_iseq;
- VALUE klass;
- GetISeqVal(sclass_iseqval, sklass_iseq);
- klass = rb_singleton_class(obj);
-
- COPY_CREF(sklass_iseq->cref_stack, th_cref_push(th, klass, NOEX_PUBLIC));
-
- /* enter scope */
- push_frame(th, sklass_iseq,
- FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
- sklass_iseq->iseq_encoded, GET_SP(), 0,
- sklass_iseq->local_size);
- RESTORE_REGS();
-
- INC_VM_STATE_VERSION();
- NEXT_INSN();
-}
-
-/**
- @c class/module
- @e enter module definition scope.
- @j W[`XR[vsB
- */
-DEFINE_INSN
-moduledef
-(ID id, VALUE module_iseqval)
-(VALUE mbase)
-(VALUE val)
-{
- yarv_iseq_t *module_iseq;
- VALUE module;
-
- if (mbase == Qnil) {
- mbase = th_get_cbase(th);
- }
-
- /* find klass */
- if (rb_const_defined_at(mbase, id)) {
- module = rb_const_get_at(mbase, id);
- /* already exist */
- if (TYPE(module) != T_MODULE) {
- rb_raise(rb_eTypeError, "%s is not a module", rb_id2name(id));
- }
- }
- else {
- /* new module declaration */
- module = rb_define_module_id(id);
- rb_set_class_path(module, mbase, rb_id2name(id));
- rb_const_set(mbase, id, module);
- }
-
- GetISeqVal(module_iseqval, module_iseq);
- COPY_CREF(module_iseq->cref_stack, th_cref_push(th, module, NOEX_PUBLIC));
-
- /* enter scope */
- push_frame(th, module_iseq,
- FRAME_MAGIC_CLASS, module, (VALUE) GET_DFP() | 0x02,
- module_iseq->iseq_encoded, GET_SP(), 0,
- module_iseq->local_size);
- RESTORE_REGS();
-
- INC_VM_STATE_VERSION();
- NEXT_INSN();
-}
-
-
/**********************************************************/
/* deal with control flow 2: method/iterator */
/**********************************************************/
@@ -1157,7 +1110,7 @@
*/
DEFINE_INSN
send
-(ID id, num_t op_argc, BLOCKISEQ blockiseq, num_t op_flag, IC ic)
+(ID id, num_t op_argc, ISEQ blockiseq, num_t op_flag, IC ic)
(...)
(VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
{
@@ -1260,8 +1213,8 @@
@j super(args) # args.size => num
*/
DEFINE_INSN
-super
-(num_t op_argc, BLOCKISEQ blockiseq, num_t flag)
+invokesuper
+(num_t op_argc, ISEQ blockiseq, num_t flag)
(...)
(VALUE val) // inc += - op_argc;
{
@@ -1285,7 +1238,7 @@
@j yield(args) # args.size => num
*/
DEFINE_INSN
-yield
+invokeblock
(num_t num, num_t flag)
(...)
(VALUE val) // inc += 1 - num;
@@ -1344,7 +1297,7 @@
@j XR[vB
*/
DEFINE_INSN
-end
+leave
()
(VALUE val)
(VALUE val)
@@ -1495,7 +1448,7 @@
@j val false nil APC (PC + dst) B
*/
DEFINE_INSN
-if
+branchif
(OFFSET dst)
(VALUE val)
()
@@ -1512,7 +1465,7 @@
@j val false nil APC (PC + dst) B
*/
DEFINE_INSN
-unless
+branchunless
(OFFSET dst)
(VALUE val)
()
Modified: trunk/rb/insns2vm.rb
===================================================================
--- trunk/rb/insns2vm.rb 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/rb/insns2vm.rb 2006-04-07 02:18:53 UTC (rev 483)
@@ -838,8 +838,8 @@
"TS_VARIABLE"
when /^CDHASH/
"TS_CDHASH"
- when /^BLOCKISEQ/
- "TS_BLOCKISEQ"
+ when /^ISEQ/
+ "TS_ISEQ"
else
raise "unknown op type: #{op}"
end
@@ -855,7 +855,7 @@
'TS_GENTRY' => 'G',
'TS_IC' => 'C',
'TS_CDHASH' => 'H',
- 'TS_BLOCKISEQ' => 'B',
+ 'TS_ISEQ' => 'S',
'TS_VARIABLE' => '.',
}
Modified: trunk/rb/yasm.rb
===================================================================
--- trunk/rb/yasm.rb 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/rb/yasm.rb 2006-04-07 02:18:53 UTC (rev 483)
@@ -1,316 +1,259 @@
#
# YASM: YARV Assembler
#
-raise "YASM is currently not supported"
-
-=begin
-
-== Usage:
-
-require 'yasm'
-yasm = YARVCore::Assembler.new
-
-
+# Usage: See examples on the end of this file.
#
-# def m1(a, b)
-# p [a, b]
-# end
-# =>
-m1 = yasm.method(:m1, :a, :b){|x|
- x.putself
- x.getlocal :a
- x.getlocal :b
- x.newarray 2
- x.send :p, 2
- x.putnil
- x.end
-}
-
-#
-# def m2(a1, a2)
-# begin
-# t1()
-# rescue
-# t2()
-# ensure
-# t3()
-# end
-# end
-m2 = yasm.method(:m2, :a1, :a2){|x|
- x.begin{|y|
- y.putself
- y.send :t1, 0
- }.rescue{|y|
- y.putself
- y.send :t2, 0
- }.ensure{|y|
- y.putself
- y.send :t3, 0
- }
-}
-
-
-#
-# def m3(a) # abs
-# if a > 0
-# a
-# else
-# -a
-# end
-# end
-m3 = yasm.method(:m3, :a){|x|
- x.getlocal :a
- x.putobject 0
- x.send :>, 1
- x.unless :lelse
- x.getlocal :a
- x.jump :lend
-x.label :lelse ##
- x.getlocal :a
- x.send :+@, 0
-x.label :lend ##
- x.end
-}
-
-
-#
-# def m4(a)
-# 3.times{|i|
-# p a
-# }
-# end
-m4 = yasm.method(:m4, :a){|x|
- x.putobject 3
- x.send :times, 0, x.block(:i){|y|
- y.getself
- y.getlocal :a
- y.send :p, 1
- y.end
- }
- x.end
-}
-
-
-#
-# def m5(a)
-# b = a * 2
-# end
-m5 = yasm.method(:a){|x|
- x.local_vars(:b) # you must declare local variables at first
- x.getlocal :a
- x.putobject 2
- x.send :*, 1
- x.dup
- x.setlocal :b
- x.end
-}
-
-
-
-
-#
-# def m1(...); ...; end
-#
-# m1(1, 2)
-# =>
-top = yasm.top{|x|
- x.methoddef(:m1, m1)
- x.putself
- x.putobject 1
- x.putobject 2
- x.send :m1, 2
- x.end
-}
-
-top = yasm.top{|x|
- x.methoddef(:m1, :a){|y|
- y.putself
- y.getlocal :a
- y.send :p, 1
- y.end
- }
- x.putself
- x.putobject 1
- x.send :m1, 1
- x.end
-}
-
-top = yasm.top{|x|
- x.putself
- x.putobject 1
- x.send :p, 1
-}
-
-#=> run
-YARVCore::eval_parsed(top)
-
-=end
-
-require 'yarvcore'
require 'yasmdata'
module YARVCore
class Assembler
+ def self.toplevel vars = [], &b
+ sdb = SimpleDataBuilder.new(
+ :toplevel, "<toplevel@yasm>", "<yasm>",
+ [], vars, [nil], nil
+ )
+ sdb.instance_eval(&b)
+ sdb
+ end
- # from yarvcore.h
- ISeqType = {
- :top => 1,
- :method => 2,
- :block => 3,
- :class => 4,
- :rescue => 5,
- :ensure => 6,
- }
+ def self.method name, args = [], vars = [], &b
+ sdb = SimpleDataBuilder.new(
+ :method, name, "TODO: filename",
+ args, vars, [nil], nil
+ )
+ sdb.instance_eval(&b)
+ sdb
+ end
- class ScopeAssember
- def initialize scope_type, id, file_name, parent, args = []
- @st = scope_type
- @seq = []
- @args = args
- @locals = []
- @labels = {}
- @parent = parent || false
- @file_name = file_name
-
- # null iseq
- @iseq = YARVCore::InstructionSequence.new(
- false, id.to_s, file_name,
- parent ? parent.iseq : nil, ISeqType[scope_type])
+ class SimpleDataBuilder
+ def initialize type, name, filename, args, vars, lopt, parent
+ @type = type
+ @name = name
+ @filename = filename
+ @args = args || []
+ @vars = vars || []
+ @locals = args + vars + lopt
+ @line = []
+ @body = []
+ @exception = []
+ @parent_sdb = parent
+ @local_sdb = parent ? parent.local_sdb : self
end
- attr_reader :iseq
-
- def set_parent parent
- @parent = parent
- end
- def local_vars *vars
- @locals = vars
- end
-
- def assemble
- @iseq.assemble @args, @locals, @seq
- end
+ attr_reader :body
+ attr_reader :locals
+ attr_reader :local_sdb, :parent_sdb
- def block *args
- sa = ScopeAssember.new(:block, 'block', @file_name, self, args)
- sa.set_parent self
- yield(sa)
- sa.assemble
+ def to_simpledata
+ # [magic, major_version, minor_version, format_type, misc,
+ # name, filename, line,
+ # type, args, vars, exception_table, body]
+ ['YARVInstructionSimpledataFormat', 1, 1, 1, nil,
+ @name, @filename, @line,
+ @type, @args, @vars, @exception, @body]
end
- def rescue
- sa = ScopeAssember.new(:rescue, 'rescue', args)
- sa.set_parent self
- yield(sa)
- sa.assemble
+ def to_iseq
+ YARVCore::InstructionSequence.load_simpledata(self.to_simpledata)
end
- def ensure
- sa = ScopeAssember.new(:ensure, 'ensure', args)
- sa.set_parent self
- yield(sa)
- sa.assemble
+ def method name, args=[], vars=[], &b
+ YASM.method(name, args, vars, &b).to_simpledata
end
-
- ##
- def make_insn id, *args
- if insn_no = YARVCore::InstructionSequence::Instruction.id2insn_no(id)
- /\:(\d+)\Z/ =~ caller(1)[1]
- line = $1.to_i
- @seq << YARVCore::InstructionSequence::Instruction.make(insn_no, line, args)
- true
- end
+
+ def block args=[], vars=[], &b
+ sdb = SimpleDataBuilder.new(
+ :block, "block", "TODO: filename",
+ args, vars, [], self
+ )
+ sdb.instance_eval(&b)
+ sdb.to_simpledata
end
- def search_local sym
- @args.each_with_index{|e, i|
- return 1 + i if e == sym
+ # label
+
+ def label sym
+ raise "Label must be Symbol, but #{sym.class}" unless Symbol === sym
+ @body << sym
+ end
+
+ alias _ label
+ alias l label
+
+ YARVCore::InstructionSequence::Instruction::InsnID2NO.each_key{|insn|
+ define_method(insn){|*ops|
+ @body << [insn, *ops]
}
- @locals.each_with_index{|e, i|
- return 1 + i + @args.size if e == sym
- }
- raise "unknown local variable: #{sym}"
+ }
+
+ # support instructions
+
+ def send id, argc, block = nil, flag = 0
+ @body << [:send, id, argc, block, flag, nil]
end
-
- def search_label label
- if lobj = @labels[label]
- lobj
- else
- @labels[label] = YARVCore::InstructionSequence::Label.new(false)
- end
+
+ def call id, argc, block = nil
+ @body << [:send, id, argc, block, 0x04, nil]
end
-
- def label l
- @seq << search_label(l)
+
+ def sym2lidx sym
+ raise unless @locals.index(sym)
+ @local_sdb.locals.size - @local_sdb.locals.index(sym)
end
- ##
-
- def method_missing id, *args
- unless make_insn id, *args
- super
- end
+ def setlocal sym
+ @body << [:setlocal, sym2lidx(sym)]
end
-
+
def getlocal sym
- make_insn :getlocal, search_local(sym)
+ @body << [:getlocal, sym2lidx(sym)]
end
- def setlocal sym
- make_insn :setlocal, search_local(sym)
+ def sym2didx sym
+ sdb = self
+ level = 0
+ while sdb
+ if idx = sdb.locals.index(sym)
+ return [sdb.locals.size - idx, level]
+ end
+ level += 1
+ sdb = sdb.parent_sdb
+ end
+ raise "unknown local dynamic variable: #{sym}"
end
-
- def send sym, argc, block = 0, flag = 0
- make_insn :send, sym, argc, block, flag, 0
- end
- def end
- make_insn :end, @args.size + @locals.size + 1
+ def getdynamic sym
+ @body << [:getdynamic, *sym2didx(sym)]
end
- def jump l
- make_insn :jump, search_label(l)
+ def setdynamic sym
+ @body << [:setdynamic, *sym2didx(sym)]
end
- def if l
- make_insn :if, search_label(l)
+ def definemethod name, method
+ @body << [:definemethod, name, method, 0]
end
- def unless l
- make_insn :unless, search_label(l)
+ def definesingletonmethod name, method
+ @body << [:definemethod, name, method, 1]
end
-
end
-
- def initialize file_name = '*YASM*'
- @file_name = file_name
- end
+ end
+end
- attr_accessor :file_name
-
- def top id = 'top'
- # def initialize scope_type, id, file_name, parent, args = []
- sa = ScopeAssember.new(:top, id, @file_name, nil)
- yield(sa)
- sa.assemble
- end
+YASM = YARVCore::Assembler
- def class id = 'Class'
- sa = ScopeAssember.new(:class, id)
- yield(sa)
- sa.assemble
- end
- def method id, *args
- sa = ScopeAssember.new(:method, id, @file_name, nil, args)
- yield(sa)
- sa.assemble
- end
- end
-end
+if __FILE__ == $0
-hoge.each{|i|
-
+#
+# samples
+#
+
+######################################################
+
+result = YASM.toplevel([:a, :b]){
+ #
+ # a = 10
+ # b = 20
+ # p(a+b)
+ # 3.times{|i| p i}
+ #
+ putobject 10
+ setlocal :a
+ putobject 20
+ setlocal :b
+ putself
+ getlocal :a
+ getlocal :b
+ send :+, 1
+ call :p, 1 # call means send with flags 4
+ pop
+ putobject 3
+ send :times, 0, block([:i]){
+ putself
+ getdynamic :i
+ call :p, 1
+ leave
+ }
+ leave
}
+data = result.to_simpledata
+iseq = result.to_iseq
+p data
+iseq.eval #=> 30
+
+###########################################################
+
+#
+# def m1(a, b)
+# p [a, b]
+# end
+# =>
+m1 = YASM.method(:m1, [:a, :b]){
+ putself
+ getlocal :a
+ getlocal :b
+ newarray 2
+ call :p, 1
+ leave
+}
+
+#
+# def m3(a) # abs
+# if a > 0
+# a
+# else
+# -a
+# end
+# end
+m3 = YASM.method(:m3, [:a]){
+ getlocal :a
+ putobject 0
+ send :>, 1
+ branchunless :label_else
+ getlocal :a
+ jump :label_end
+_ :label_else
+ getlocal :a
+ send :+@, 0
+_ :label_end
+ leave
+}
+
+#
+# def m5(a)
+# b = a * 2
+# end
+m5 = YASM.method(:m5, [:a], [:b]){
+ getlocal :a
+ putobject 2
+ send :*, 1
+ dup
+ setlocal :b
+ leave
+}
+
+
+#
+# def m1(...); ...; end
+#
+# m1(1, 2)
+# =>
+top = YASM.toplevel{
+ putnil
+ definemethod(:m1, m1.to_simpledata)
+ putself
+ putobject 1
+ putobject 2
+ call :m1, 2
+ leave
+}
+
+#=> run
+top.to_iseq.eval
+
+###########################################################
+end
Modified: trunk/template/insns.inc.tmpl
===================================================================
--- trunk/template/insns.inc.tmpl 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/template/insns.inc.tmpl 2006-04-07 02:18:53 UTC (rev 483)
@@ -17,3 +17,5 @@
<%= insns %>
};
+#define YARV_MAX_INSTRUCTION_SIZE <%= @insns.size %>
+
Modified: trunk/vm.c
===================================================================
--- trunk/vm.c 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/vm.c 2006-04-07 02:18:53 UTC (rev 483)
@@ -1121,13 +1121,11 @@
EVALBODY_HELPER_FUNCTION void
eval_define_method(yarv_thread_t *th, VALUE obj,
- ID id, VALUE body, num_t is_singleton, NODE *cref)
+ ID id, yarv_iseq_t *miseq, num_t is_singleton, NODE *cref)
{
NODE *newbody;
- yarv_iseq_t *miseq;
int noex = cref->nd_visi;
VALUE klass = cref->nd_clss;
- GetISeqVal(body, miseq);
if (is_singleton) {
if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
@@ -1156,7 +1154,7 @@
COPY_CREF(miseq->cref_stack, cref);
miseq->klass = klass;
miseq->defined_method_id = id;
- newbody = NEW_NODE(YARV_METHOD_NODE, 0, body, 0);
+ newbody = NEW_NODE(YARV_METHOD_NODE, 0, miseq->self, 0);
rb_add_method(klass, id, newbody, noex);
if (!is_singleton && noex == NOEX_MODFUNC) {
Modified: trunk/vm_evalbody.h
===================================================================
--- trunk/vm_evalbody.h 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/vm_evalbody.h 2006-04-07 02:18:53 UTC (rev 483)
@@ -18,7 +18,7 @@
#endif
// #define DECL_SC_REG(r, reg) VALUE reg_##r
-typedef yarv_iseq_t *BLOCKISEQ;
+typedef yarv_iseq_t *ISEQ;
#if !OPT_CALL_THREADED_CODE
VALUE
Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/yarvcore.c 2006-04-07 02:18:53 UTC (rev 483)
@@ -40,8 +40,6 @@
ID idBackquote;
ID idEqTilde;
ID idThrowState;
-ID idThrowBackDFP;
-ID idThrowObject;
ID idAREF;
ID idASET;
ID idIntern;
@@ -84,6 +82,7 @@
printf(" ");
}
}
+
static void
MARK_REPORT_BODY(char *msg, int st, void *ptr)
{
@@ -156,7 +155,6 @@
return 0;
}
-
VALUE *th_svar(yarv_thread_t *self, int cnt);
VALUE *
@@ -364,6 +362,7 @@
return obj;
}
+
static VALUE
prepare_iseq_build(yarv_iseq_t *iseq,
VALUE name, VALUE file_name,
@@ -465,14 +464,87 @@
return self;
}
-VALUE iseq_assemble_setup(VALUE self, VALUE args, VALUE locals, VALUE ary);
+VALUE
+iseq_load_simpledata(VALUE self, VALUE data, VALUE parent)
+{
+ VALUE iseqval = iseq_alloc(cYarvISeq);
+ VALUE magic, version1, version2, format_type, misc;
+ VALUE name, filename, line;
+ VALUE type, body, args, vars, exception;
+
+ VALUE iseq_type;
+ struct st_table *type_map = 0;
+
+ /* [magic, major_version, minor_version, format_type, misc,
+ * name, filename, line,
+ * type, args, vars, exception_table, body]
+ */
+
+ magic = rb_ary_entry(data, 0);
+ version1 = rb_ary_entry(data, 1);
+ version2 = rb_ary_entry(data, 2);
+ format_type = rb_ary_entry(data, 3);
+ misc = rb_ary_entry(data, 4);
+
+ /* TODO: load check */
+
+ name = rb_ary_entry(data, 5);
+ filename = rb_ary_entry(data, 6);
+ line = rb_ary_entry(data, 7);
+
+ type = rb_ary_entry(data, 8);
+ args = rb_ary_entry(data, 9);
+ vars = rb_ary_entry(data, 10);
+ exception = rb_ary_entry(data, 11);
+ body = rb_ary_entry(data, 12);
+
+ yarv_iseq_t *iseq;
+ GetISeqVal(iseqval, iseq);
+ iseq->self = iseqval;
+
+ if (type_map == 0) {
+ type_map = st_init_numtable();
+ st_insert(type_map, ID2SYM(rb_intern("toplevel")), ISEQ_TYPE_TOP);
+ st_insert(type_map, ID2SYM(rb_intern("method")), ISEQ_TYPE_METHOD);
+ st_insert(type_map, ID2SYM(rb_intern("block")), ISEQ_TYPE_BLOCK);
+ st_insert(type_map, ID2SYM(rb_intern("class")), ISEQ_TYPE_CLASS);
+ st_insert(type_map, ID2SYM(rb_intern("rescue")), ISEQ_TYPE_RESCUE);
+ st_insert(type_map, ID2SYM(rb_intern("ensure")), ISEQ_TYPE_ENSURE);
+ st_insert(type_map, ID2SYM(rb_intern("eval")), ISEQ_TYPE_EVAL);
+ }
+
+ if (st_lookup(type_map,
+ type, &iseq_type) == 0) {
+ rb_raise(rb_eTypeError, "unsupport type: %p", type);
+ }
+
+ if (parent == Qnil) {
+ parent = 0;
+ }
+
+ prepare_iseq_build(iseq,
+ name, filename,
+ parent, iseq_type, 0);
+
+ iseq_simpledata2iseq(iseq, line, args, vars, exception, body);
+
+ cleanup_iseq_build(iseq);
+ return iseqval;
+}
+
static VALUE
-iseq_assemble(VALUE self, VALUE args, VALUE locals, VALUE insn_ary)
+iseq_m_load_simpledata(VALUE self, VALUE data)
{
- return iseq_assemble_setup(self, args, locals, insn_ary);
+ return iseq_load_simpledata(self, data, 0);
}
+static VALUE
+iseq_eval(VALUE self)
+{
+ return yarvcore_eval_iseq(self);
+}
+
VALUE
iseq_inspect(VALUE self)
{
@@ -486,6 +558,16 @@
return rb_str_new2(buff);
}
+VALUE iseq_iseq2simpledata(yarv_iseq_t *iseq);
+
+static VALUE
+iseq_to_simpledata(VALUE self)
+{
+ yarv_iseq_t *iseq;
+ GetISeqVal(self, iseq);
+ return iseq_iseq2simpledata(iseq);
+}
+
/******/
/* VM */
/******/
@@ -1122,7 +1204,6 @@
rb_define_singleton_method(mYarvCore, "eval", yarvcore_eval, 3);
rb_define_singleton_method(mYarvCore, "parse", yarvcore_parse, 3);
- rb_define_singleton_method(mYarvCore, "eval_iseq", yarvcore_eval_iseq, 1);
/* declare YARVCore::InstructionSequence */
cYarvISeq =
@@ -1131,8 +1212,10 @@
rb_define_method(cYarvISeq, "initialize", iseq_init, 6);
rb_define_method(cYarvISeq, "inspect", iseq_inspect, 0);
rb_define_method(cYarvISeq, "disasm", iseq_disasm, 0);
- rb_define_method(cYarvISeq, "assemble", iseq_assemble, 3);
- // rb_define_singleton_method(cYarvISeq, "new_from_insn_ary", iseq_init_from_insn_ary, 1);
+ rb_define_method(cYarvISeq, "to_simpledata", iseq_to_simpledata, 0);
+ rb_define_method(cYarvISeq, "eval", iseq_eval, 0);
+ rb_define_singleton_method(cYarvISeq, "load_simpledata",
+ iseq_m_load_simpledata, 1);
/* declare YARVCore::VM */
cYarvVM = rb_define_class_under(mYarvCore, "VM", rb_cObject);
@@ -1225,8 +1308,6 @@
idMethodMissing = rb_intern("method_missing");
idThrowState = rb_intern("#__ThrowState__");
- idThrowBackDFP = rb_intern("#__ThrowBackDFP__");
- idThrowObject = rb_intern("#__ThrowObject__");
idBitblt = rb_intern("bitblt");
idAnswer = rb_intern("the_answer_to_life_the_universe_and_everything");
Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h 2006-03-08 01:32:31 UTC (rev 482)
+++ trunk/yarvcore.h 2006-04-07 02:18:53 UTC (rev 483)
@@ -107,8 +107,6 @@
extern ID idBackquote;
extern ID idEqTilde;
extern ID idThrowState;
-extern ID idThrowBackDFP;
-extern ID idThrowObject;
extern ID idAREF;
extern ID idASET;
extern ID idIntern;
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml