yarv-diff:133
From: ko1 atdot.net
Date: 18 Nov 2005 20:59:48 -0000
Subject: [yarv-diff:133] r290 - in trunk: . yarvtest
Author: ko1
Date: 2005-11-19 05:59:48 +0900 (Sat, 19 Nov 2005)
New Revision: 290
Modified:
trunk/ChangeLog
trunk/compile.c
trunk/compile.h
trunk/eval.c
trunk/eval_proc.c
trunk/insns.def
trunk/test.rb
trunk/vm.c
trunk/vm_dump.c
trunk/yarvcore.c
trunk/yarvtest/test_syn.rb
Log:
* compile.c : useless jump elimination (if/unless destination)
* eval.c : rb_iter_break support,
fix rb_iterate (clear errinfo if break)
* eval_proc.c : support rb_node_arity (YARV_METHOD_NODE)
* insns.def : change variable name
* vm.c : fix th_invoke_yield and add th_iter_break()
* vm_dump.c : fix yarv_bug()
* yarvcore.c : fix proc_mark to check IFUNC node and add
global ruby method SDR() for debug
* yarvtest/test_syn.rb : add a test for all condition combination
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/ChangeLog 2005-11-18 20:59:48 UTC (rev 290)
@@ -4,7 +4,27 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2005-11-19(Sat) 05:48:50 +0900 Koichi Sasada <ko1 atdot.net>
+ * compile.c : useless jump elimination (if/unless destination)
+
+ * eval.c : rb_iter_break support,
+ fix rb_iterate (clear errinfo if break)
+
+ * eval_proc.c : support rb_node_arity (YARV_METHOD_NODE)
+
+ * insns.def : change variable name
+
+ * vm.c : fix th_invoke_yield and add th_iter_break()
+
+ * vm_dump.c : fix yarv_bug()
+
+ * yarvcore.c : fix proc_mark to check IFUNC node and add
+ global ruby method SDR() for debug
+
+ * yarvtest/test_syn.rb : add a test for all condition combination
+
+
2005-11-15(Tue) 05:52:58 +0900 Koichi Sasada <ko1 atdot.net>
* lib/forwardable.rb : added
Modified: trunk/compile.c
===================================================================
--- trunk/compile.c 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/compile.c 2005-11-18 20:59:48 UTC (rev 290)
@@ -66,7 +66,9 @@
static void debug_list(LINK_ANCHOR *anchor);
#endif
+void dump_disasm_anchor(LINK_ANCHOR *anc);
void dump_disasm_list(LINK_ELEMENT* elem);
+
static int insn_data_length(INSN *insnobj);
static int insn_data_line_no(INSN *insnobj);
static int insn_ret_num(int insn);
@@ -237,7 +239,7 @@
iseqobj->type == ISEQ_TYPE_ENSURE){
ADD_INSN2(list_anchor, 0, getdynamic, I2F(1), I2F(0));
- ADD_INSN1(list_anchor, 0, throw, I2F(0));
+ ADD_INSN1(list_anchor, 0, throw, I2F(0) /* continue throw */);
}
else{
ADD_INSN(list_anchor, iseqobj->compile_data->last_line, end);
@@ -429,10 +431,6 @@
return anchor->anchor.next;
}
-static void dump_disasm_anchor(LINK_ANCHOR *anc){
- dump_disasm_list(FIRST_ELEMENT(anc));
-}
-
static LINK_ELEMENT *
LAST_ELEMENT(LINK_ANCHOR *anchor)
{
@@ -1426,22 +1424,23 @@
iseq_optimize(yarv_iseq_t *iseqobj, LINK_ANCHOR *anchor)
{
LINK_ELEMENT *list;
- /*
- * useless jump elimination:
- * jump LABEL1
- * ...
- * LABEL1:
- * jump LABEL2
- *
- * => in this case, first jump instruction should jump tp
- * LABEL2 directly
- */
list = FIRST_ELEMENT(anchor);
// dump_disasm_list(list);
while(list){
if(list->type == ISEQ_ELEMENT_INSN){
- INSN *niobj, *diobj, *piobj, *iobj = (INSN *)list;
+ INSN *iobj = (INSN *)list;
if(iobj->insn_id == BIN(jump)){
+ INSN *niobj, *diobj, *piobj;
+ /*
+ * useless jump elimination:
+ * jump LABEL1
+ * ...
+ * LABEL1:
+ * jump LABEL2
+ *
+ * => in this case, first jump instruction should jump tp
+ * LABEL2 directly
+ */
diobj = (INSN*)get_destination_insn(iobj);
niobj = (INSN*)get_next_insn(iobj);
@@ -1460,6 +1459,7 @@
(LINK_ELEMENT *)eiobj);
}
/*
+ * useless jump elimination (if/unless destination):
* if L1
* jump L2
* L1:
@@ -1481,7 +1481,26 @@
REMOVE_ELEM(&iobj->link);
}
}
+ if(0){
+ debugs("jump: \n");
+ dump_disasm_anchor(anchor);
+ }
}
+ if(iobj->insn_id == BIN(if) ||
+ iobj->insn_id == BIN(unless)){
+ /*
+ * if L1
+ * ...
+ * L1:
+ * jump L2
+ * =>
+ * if L2
+ */
+ INSN *nobj = (INSN *)get_destination_insn(iobj);
+ if(nobj->insn_id == BIN(jump)){
+ OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
+ }
+ }
if(iobj->insn_id == BIN(end)){
INSN *piobj = (INSN*)get_prev_insn((INSN*)list);
@@ -1818,7 +1837,7 @@
break;
}
default:
- COMPILE(ret, "branch condition", cond);
+ COMPILE (ret, "branch condition", cond);
ADD_INSNL(ret, nd_line(cond), unless, else_label);
ADD_INSNL(ret, nd_line(cond), jump, then_label);
break;
@@ -2580,9 +2599,9 @@
ADD_INSNL(ret, nd_line(node), jump, iseqobj->compile_data->end_label);
}
else if(iseqobj->type == ISEQ_TYPE_BLOCK){
- break_by_jump:
+ break_by_insn:
/* escape from block */
- COMPILE(ret, "break val(block)", node->nd_stts);
+ COMPILE(ret, "break val (block)", node->nd_stts);
ADD_INSN1(ret, nd_line(node), throw, I2F(level | 0x02) /* TAG_BREAK */);
}
else{
@@ -2592,20 +2611,19 @@
level++;
if(ip->type == ISEQ_TYPE_BLOCK){
level <<= 16;
- goto break_by_jump;
+ goto break_by_insn;
}
else if(ip->compile_data->redo_label != 0){
level = 0x8000;
if(ip->compile_data->loopval_popped == 0){
level |= 0x4000;
}
- goto break_by_jump;
+ goto break_by_insn;
}
ip = ip->parent_iseq;
}
COMPILE_ERROR(("can't put break"));
}
-
break;
}
case NODE_NEXT:{
@@ -2821,7 +2839,7 @@
node->nd_head, /* lhsn */
0);
if(!poped){
- ADD_INSN(ret, nd_line(node), putnil);
+ ADD_INSN1(ret, nd_line(node), putobject, Qtrue);
}
break;
}
@@ -4131,6 +4149,11 @@
}
void
+dump_disasm_anchor(LINK_ANCHOR *anc){
+ dump_disasm_list(FIRST_ELEMENT(anc));
+}
+
+void
dump_disasm_list(struct iseq_link_element *link)
{
int pos = 0;
Modified: trunk/compile.h
===================================================================
--- trunk/compile.h 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/compile.h 2005-11-18 20:59:48 UTC (rev 290)
@@ -28,7 +28,7 @@
#if 0
#undef CPDEBUG
-#define CPDEBUG 2
+#define CPDEBUG 10
#endif
#if CPDEBUG > 0
Modified: trunk/eval.c
===================================================================
--- trunk/eval.c 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/eval.c 2005-11-18 20:59:48 UTC (rev 290)
@@ -893,13 +893,12 @@
return Qfalse;
}
+NORETURN(void th_iter_break _((yarv_thread_t *)));
-
-
void
rb_iter_break()
{
- UNSUPPORTED(rb_iter_break)
+ th_iter_break(GET_THREAD());
}
NORETURN(static void rb_longjmp _((int, VALUE)));
@@ -1186,11 +1185,11 @@
argc = RARRAY(argv[0])->len;
argv = RARRAY(argv[0])->ptr;
}
-
return th_invoke_yield(GET_THREAD(), argc, argv);
}
}
+
VALUE
rb_yield(val)
VALUE val;
@@ -1290,14 +1289,18 @@
else if (state == TAG_BREAK /* TODO: more check */ ) {
// TODO: Fix me
state = 0;
+ th->state = 0;
+ th->errinfo = Qnil;
}
else if (state == TAG_RETRY) {
state = 0;
+ th->state = 0;
+ th->errinfo = Qnil;
goto iter_retry;
}
TH_POP_TAG();
- switch (state) {
+ switch (state){
case 0:
break;
default:
Modified: trunk/eval_proc.c
===================================================================
--- trunk/eval_proc.c 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/eval_proc.c 2005-11-18 20:59:48 UTC (rev 290)
@@ -831,35 +831,45 @@
}
int
-rb_node_arity(body)
- NODE *body;
+rb_node_arity(NODE *body)
{
- int n;
+ int n;
- switch (nd_type(body)) {
- case NODE_CFUNC:
- if (body->nd_argc < 0) return -1;
- return body->nd_argc;
- case NODE_ZSUPER:
- return -1;
- case NODE_ATTRSET:
- return 1;
- case NODE_IVAR:
- return 0;
- case NODE_BMETHOD:
- return rb_proc_arity(body->nd_cval);
- case NODE_SCOPE:
- body = body->nd_next; /* skip NODE_SCOPE */
- if (nd_type(body) == NODE_BLOCK)
- body = body->nd_head;
- if (!body) return 0;
- n = body->nd_frml ? RARRAY(body->nd_frml)->len : 0;
- if (body->nd_opt || body->nd_rest)
- n = -n-1;
- return n;
- default:
- rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
+ switch (nd_type(body)) {
+ case NODE_CFUNC:
+ if (body->nd_argc < 0) return -1;
+ return body->nd_argc;
+ case NODE_ZSUPER:
+ return -1;
+ case NODE_ATTRSET:
+ return 1;
+ case NODE_IVAR:
+ return 0;
+ case NODE_BMETHOD:
+ return rb_proc_arity(body->nd_cval);
+ case NODE_SCOPE:
+ body = body->nd_next; /* skip NODE_SCOPE */
+ if (nd_type(body) == NODE_BLOCK)
+ body = body->nd_head;
+ if (!body) return 0;
+ n = body->nd_frml ? RARRAY(body->nd_frml)->len : 0;
+ if (body->nd_opt || body->nd_rest)
+ n = -n-1;
+ return n;
+ case YARV_METHOD_NODE:{
+ yarv_iseq_t *iseq;
+ GetISeqVal((VALUE)body->nd_body, iseq);
+ if(iseq->arg_rest == 0 &&
+ iseq->arg_opts == 0){
+ return iseq->argc;
}
+ else{
+ return -iseq->argc-1;
+ }
+ }
+ default:
+ rb_raise(rb_eArgError, "invalid node 0x%x", nd_type(body));
+ }
}
/*
@@ -998,7 +1008,6 @@
bmcall(VALUE args, VALUE method)
{
volatile VALUE a;
-
if(CLASS_OF(args) != rb_cArray){
args = rb_ary_new3(1, args);
}
Modified: trunk/insns.def
===================================================================
--- trunk/insns.def 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/insns.def 2005-11-18 20:59:48 UTC (rev 290)
@@ -1518,7 +1518,7 @@
}
}
else{
- if(state == TAG_BREAK || throw_state == TAG_RETRY){
+ if(state == TAG_BREAK || state == TAG_RETRY){
pt = GC_GUARDED_PTR_REF((VALUE*)*GET_DFP());
for(i=0; i<level; i++){
pt = GC_GUARDED_PTR_REF((VALUE*)*pt);
Modified: trunk/test.rb
===================================================================
--- trunk/test.rb 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/test.rb 2005-11-18 20:59:48 UTC (rev 290)
@@ -1,2 +1,12 @@
+$:.unshift './lib'
+
require 'test/unit'
+GC.start
+class Foo < Test::Unit::TestCase
+ def test_foo
+ assert_equal(1, 2)
+ end
+end
+
+
Modified: trunk/vm.c
===================================================================
--- trunk/vm.c 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/vm.c 2005-11-18 20:59:48 UTC (rev 290)
@@ -511,7 +511,7 @@
}
}
else{
- if(argc == 1 && !IMMEDIATE_P(argv[0]) &&
+ if(argc == 1 && !SPECIAL_CONST_P(argv[0]) &&
BUILTIN_TYPE(argv[0]) == T_ARRAY){
argc = RARRAY(argv[0])->len;
argv = RARRAY(argv[0])->ptr;
@@ -795,8 +795,6 @@
return th_backtrace(th, level);
}
-
-
/*
*
* vm main loop helper functions
@@ -1021,6 +1019,15 @@
rb_exc_raise(exc);
}
+void
+th_iter_break(yarv_thread_t *th){
+ yarv_control_frame_t *cfp = th->cfp;
+ VALUE *dfp = GC_GUARDED_PTR_REF(*cfp->dfp);
+
+ th->state = TAG_BREAK;
+ th->errinfo = (VALUE)NEW_THROW_OBJECT(Qnil, (VALUE)dfp, TAG_BREAK);
+ TH_JUMP_TAG(th, TAG_BREAK);
+}
VALUE yarv_unredefined_flag = 0x01;
@@ -1167,9 +1174,12 @@
exception_handler:
cont_pc = cont_sp = catch_iseqval = 0;
- while(th->cfp->pc == 0 || th->cfp->iseq == 0){
+
+ while(th->cfp->pc == 0 ||
+ th->cfp->iseq == 0){
th->cfp++;
}
+
cfp = th->cfp;
epc = cfp->pc - cfp->iseq->iseq_encoded;
Modified: trunk/vm_dump.c
===================================================================
--- trunk/vm_dump.c 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/vm_dump.c 2005-11-18 20:59:48 UTC (rev 290)
@@ -487,6 +487,10 @@
void
yarv_bug(){
yarv_thread_t *th = GET_THREAD();
- dp(th_backtrace(th, 0));
+ VALUE bt = th_backtrace(th, 0);
+ int i;
+ for(i=0; i<RARRAY(bt)->len; i++){
+ dp(RARRAY(bt)->ptr[i]);
+ }
SDR();
}
Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/yarvcore.c 2005-11-18 20:59:48 UTC (rev 290)
@@ -65,24 +65,28 @@
#if MARK_FREE_DEBUG
static int g_indent = 0;
-static void gc_debug_indent(){
+
+static void
+gc_debug_indent(){
int i;
for(i=0; i<g_indent; i++){
printf(" ");
}
}
-void MARK_REPORT(char *msg, int st){
+static void
+MARK_REPORT_BODY(char *msg, int st, void *ptr){
if(st == 0){
g_indent--;
}
gc_debug_indent();
- printf("mark: %s\n", msg);
+ printf("mark: %s (%p)\n", msg, ptr);
if(st){
g_indent++;
}
}
+#define MARK_REPORT(msg, st) MARK_REPORT_BODY(msg, st, ptr)
#define GC_INFO gc_debug_indent(); printf
-#define FREE_REPORT(msg) printf("free: %s\n", msg)
+#define FREE_REPORT(msg) printf("free: %s (%p)\n", msg, ptr)
#else
#define MARK_REPORT(msg, st)
@@ -775,9 +779,13 @@
yarv_proc_t *proc;
MARK_REPORT("-> proc", 1);
if(ptr){
+
proc = ptr;
MARK_UNLESS_NULL(proc->envval);
MARK_UNLESS_NULL(proc->blockprocval);
+ if(BUILTIN_TYPE(proc->block.iseq) == T_NODE){
+ MARK_UNLESS_NULL((VALUE)(proc->block.iseq));
+ }
}
MARK_REPORT("<- proc", 0);
}
@@ -831,6 +839,11 @@
VALUE Init_yarvthread();
extern VALUE *rb_gc_stack_start;
+VALUE
+sdr(){
+ yarv_bug();
+ return Qnil;
+}
char yarv_version[0x20];
char *yarv_options = ""
#if OPT_DIRECT_THREADED_CODE
@@ -934,6 +947,7 @@
rb_define_global_function("once", yarv_once, 0);
rb_define_global_function("cfunc", cfunc, 0);
rb_define_global_function("yarv_caller", yarv_caller, 1);
+ rb_define_global_function("SDR", sdr, 0);
/* Integer#times */
rb_define_method(rb_cInteger, "times", yarv_Integer_times, 0);
Modified: trunk/yarvtest/test_syn.rb
===================================================================
--- trunk/yarvtest/test_syn.rb 2005-11-14 21:00:51 UTC (rev 289)
+++ trunk/yarvtest/test_syn.rb 2005-11-18 20:59:48 UTC (rev 290)
@@ -454,8 +454,70 @@
defined?(a.class)
}
end
-
-end
+ def test_condition
+ ae %q{
+ def make_perm ary, num
+ if num == 1
+ ary.map{|e| [e]}
+ else
+ base = make_perm(ary, num-1)
+ res = []
+ base.each{|b|
+ ary.each{|e|
+ res << [e] + b
+ }
+ }
+ res
+ end
+ end
+
+ def each_test
+ conds = make_perm(['fv', 'tv'], 3)
+ bangs = make_perm(['', '!'], 3)
+ exprs = make_perm(['and', 'or'], 3)
+ ['if', 'unless'].each{|syn|
+ conds.each{|cs|
+ bangs.each{|bs|
+ exprs.each{|es|
+ yield(syn, cs, bs, es)
+ }
+ }
+ }
+ }
+ end
+
+ fv = false
+ tv = true
+
+ $ans = []
+ each_test{|syn, conds, bangs, exprs|
+ c1, c2, c3 = conds
+ bang1, bang2, bang3 = bangs
+ e1, e2 = exprs
+ eval %Q{
+ #{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3}
+ $ans << :then
+ else
+ $ans << :false
+ end
+ }
+ }
+
+ each_test{|syn, conds, bangs, exprs|
+ c1, c2, c3 = conds
+ bang1, bang2, bang3 = bangs
+ e1, e2 = exprs
+ eval %Q{
+ #{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3}
+ $ans << :then
+ end
+ $ans << :sep
+ }
+ }
+ $ans
+ }
+ end
+end
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml