yarv-diff:144
From: ko1 atdot.net
Date: 4 Dec 2005 19:07:53 -0000
Subject: [yarv-diff:144] r303 - in trunk: . yarvtest
Author: ko1
Date: 2005-12-05 04:07:52 +0900 (Mon, 05 Dec 2005)
New Revision: 303
Modified:
trunk/ChangeLog
trunk/array.c
trunk/blockinlining.c
trunk/compile.c
trunk/disasm.c
trunk/insns.def
trunk/test.rb
trunk/vm.c
trunk/yarvcore.h
trunk/yarvtest/test_flow.rb
Log:
* array.c, blockinlining.c : support block inlining for Array#each
* disasm.c : fix catch table format
* insns.def : fix stack consistency error message
* vm.c : fix to skip pushing value at "next"
* yarvcore.h : move definision of
"struct iseq_compile_data_ensure_node_stack" to compile.c
* compile.c : fix ensure catch table creation
* yarvtest/test_flow.rb : add tests for above
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/ChangeLog 2005-12-04 19:07:52 UTC (rev 303)
@@ -4,6 +4,24 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2005-12-05(Mon) 03:58:30 +0900 Koichi Sasada <ko1 atdot.net>
+
+ * array.c, blockinlining.c : support block inlining for Array#each
+
+ * disasm.c : fix catch table format
+
+ * insns.def : fix stack consistency error message
+
+ * vm.c : fix to skip pushing value at "next"
+
+ * yarvcore.h : move definision of
+ "struct iseq_compile_data_ensure_node_stack" to compile.c
+
+ * compile.c : fix ensure catch table creation
+
+ * yarvtest/test_flow.rb : add tests for above
+
+
2005-12-03(Sat) 22:27:08 +0900 Koichi Sasada <ko1 atdot.net>
* blockinlining.c, compile.c, yarvcore.c, yarvcore.h,
Modified: trunk/array.c
===================================================================
--- trunk/array.c 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/array.c 2005-12-04 19:07:52 UTC (rev 303)
@@ -1133,13 +1133,20 @@
VALUE
rb_ary_each(VALUE ary)
{
- long i;
+ long i;
+ VALUE val;
+
+ RETURN_ENUMERATOR(ary, 0, 0);
- RETURN_ENUMERATOR(ary, 0, 0);
- for (i=0; i<RARRAY(ary)->len; i++) {
- rb_yield(RARRAY(ary)->ptr[i]);
- }
- return ary;
+ val = yarv_invoke_Array_each_special_block(ary);
+ if(val != Qundef){
+ return val;
+ }
+
+ for (i=0; i<RARRAY(ary)->len; i++) {
+ rb_yield(RARRAY(ary)->ptr[i]);
+ }
+ return ary;
}
/*
Modified: trunk/blockinlining.c
===================================================================
--- trunk/blockinlining.c 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/blockinlining.c 2005-12-04 19:07:52 UTC (rev 303)
@@ -256,3 +256,113 @@
return Qundef;
}
+
+static NODE *
+build_Array_each_node(yarv_iseq_t *iseq, NODE *node,
+ VALUE param_vars, VALUE local_vars)
+{
+ /* Special block for Array#each
+ ary.each{|e|
+ BODY
+ }
+ =>
+ {|e, _self|
+ _i = 0
+ while _i < _self.length
+ e = _self[_i]
+ redo_point:
+ BODY
+ next_point:
+ _i = _i.succ
+ end
+ }
+
+ ary.each{
+ BODY
+ }
+ =>
+ {|_i, _self|
+ _i = 0
+ while _i < _self.length
+ redo_point:
+ BODY
+ next_point:
+ _i = _i.succ
+ end
+ }
+ */
+
+ ID _self = rb_intern("#_self");
+ ID _i = rb_intern("#_i");
+
+ if(iseq->argc == 0){
+ ID _e = rb_intern("#_e");
+ rb_ary_push(param_vars, ID2SYM(_e));
+ rb_ary_push(param_vars, ID2SYM(_self));
+ iseq->argc+=2;
+ rb_ary_push(local_vars, ID2SYM(_i));
+
+ node =
+ new_block(
+ NEW_DASGN(_i, NEW_LIT(INT2FIX(0))),
+ NEW_WHILE(
+ NEW_CALL(NEW_DVAR(_i), idLT,
+ new_ary(NEW_CALL(NEW_DVAR(_self), idLength, 0), 0)),
+ new_block(NEW_OPTBLOCK(node),
+ NEW_DASGN(_i, NEW_CALL(NEW_DVAR(_i), idSucc, 0))),
+ Qundef));
+ }
+ else{
+ ID e = SYM2ID(rb_ary_entry(param_vars, 0));
+ rb_ary_push(param_vars, ID2SYM(_self));
+ iseq->argc++;
+ rb_ary_push(local_vars, ID2SYM(_i));
+
+ node =
+ new_block(
+ NEW_DASGN(_i, NEW_LIT(INT2FIX(0))),
+ NEW_WHILE(
+ NEW_CALL(NEW_DVAR(_i), idLT,
+ new_ary(NEW_CALL(NEW_DVAR(_self), idLength, 0), 0)),
+ new_block(
+ NEW_DASGN(e,
+ NEW_CALL(NEW_DVAR(_self), idAREF, new_ary(NEW_DVAR(_i), 0))),
+ new_block(NEW_OPTBLOCK(node),
+ NEW_DASGN(_i, NEW_CALL(NEW_DVAR(_i), idSucc, 0)))),
+ Qundef));
+ }
+ return node;
+}
+
+VALUE
+yarv_invoke_Array_each_special_block(VALUE ary)
+{
+ yarv_thread_t *th = GET_THREAD();
+ yarv_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
+
+ if(BUILTIN_TYPE(orig_block->iseq) != T_NODE){
+ VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq,
+ build_Array_each_node);
+ yarv_iseq_t *tsiseq;
+ VALUE argv[2];
+
+ if(tsiseqval){
+ VALUE val;
+ yarv_block_t block = *orig_block;
+ GetISeqVal(tsiseqval, tsiseq);
+ block.iseq = tsiseq;
+ th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
+ argv[0] = 0;
+ argv[1] = ary;
+ val = th_invoke_yield(th, 2, argv);
+ if(val == Qundef){
+ return ary;
+ }
+ else{
+ return val;
+ }
+ }
+ }
+ return Qundef;
+}
+
Modified: trunk/compile.c
===================================================================
--- trunk/compile.c 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/compile.c 2005-12-04 19:07:52 UTC (rev 303)
@@ -58,7 +58,19 @@
VALUE *operands;
} INSN;
+struct ensure_range{
+ LABEL *begin;
+ LABEL *end;
+ struct ensure_range *next;
+};
+struct iseq_compile_data_ensure_node_stack{
+ NODE* ensure_node;
+ struct iseq_compile_data_ensure_node_stack *prev;
+ struct ensure_range *erange;
+};
+
+
/* for debug */
#if CPDEBUG > 0
static long gl_node_level = 0;
@@ -2305,21 +2317,48 @@
return rb_str_new2(buf);
}
+static void
+add_ensure_range(yarv_iseq_t *iseq, struct ensure_range *erange,
+ LABEL *lstart, LABEL *lend)
+{
+ struct ensure_range *ne =
+ compile_data_alloc(iseq, sizeof(struct ensure_range));
+
+ while(erange->next != 0){
+ erange = erange->next;
+ }
+ ne->next = 0;
+ ne->begin = lend;
+ ne->end = erange->end;
+ erange->end = lstart;
+ erange->next = ne;
+}
+
static void
add_ensure_iseq(LINK_ANCHOR *ret, yarv_iseq_t *iseq, VALUE self)
{
- struct iseq_compile_data_ensure_node_stack *enlp = iseq->compile_data->ensure_node_stack;
+ struct iseq_compile_data_ensure_node_stack *enlp =
+ iseq->compile_data->ensure_node_stack;
+ struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
+
DECL_ANCHOR(ensure);
-
while(enlp){
DECL_ANCHOR(ensure_part);
LINK_ANCHOR *t;
+ LABEL *lstart = NEW_LABEL(0);
+ LABEL *lend = NEW_LABEL(0);
+ add_ensure_range(iseq, enlp->erange, lstart, lend);
+
+ iseq->compile_data->ensure_node_stack = enlp->prev;
+ ADD_LABEL(ensure_part, lstart);
COMPILE_POPED(ensure_part, "ensure part", enlp->ensure_node);
+ ADD_LABEL(ensure_part, lend);
ADD_SEQ(ensure, ensure_part);
enlp = enlp->prev;
}
+ iseq->compile_data->ensure_node_stack = prev_enlp;
ADD_SEQ(ret, ensure);
}
@@ -2591,9 +2630,9 @@
}
ADD_LABEL(ret, redo_label);
- COMPILE_ (ret, "while body", node->nd_body, 1);
+ COMPILE_POPED(ret, "while body", node->nd_body);
ADD_LABEL(ret, next_label); /* next */
-
+
if(type == NODE_WHILE){
compile_branch_condition(self, iseq, ret,
node->nd_cond, redo_label, end_label);
@@ -2674,9 +2713,9 @@
if(iseq->compile_data->redo_label != 0){
/* while/until */
+ add_ensure_iseq(ret, iseq, self);
COMPILE_(ret, "break val(while/until)", node->nd_stts,
iseq->compile_data->loopval_popped);
- add_ensure_iseq(ret, iseq, self);
ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->end_label);
}
else if(iseq->type == ISEQ_TYPE_BLOCK){
@@ -2856,12 +2895,14 @@
LABEL * lend = NEW_LABEL(nd_line(node));
LABEL * lcont = NEW_LABEL(nd_line(node));
VALUE prev_in_ensure = iseq->compile_data->in_ensure;
+ struct ensure_range er = {lstart, lend, 0};
struct iseq_compile_data_ensure_node_stack enl = {
node->nd_ensr,
- iseq->compile_data->ensure_node_stack /* prev */
+ iseq->compile_data->ensure_node_stack, /* prev */
+ &er,
};
+ struct ensure_range *erange;
-
iseq->compile_data->in_ensure = Qtrue;
COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr);
@@ -2879,7 +2920,11 @@
}
ADD_LABEL(ret, lcont);
- ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, lstart, lend, ensure, 0, lcont);
+ erange = iseq->compile_data->ensure_node_stack->erange;
+ while(erange){
+ ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end, ensure, 0, lcont);
+ erange = erange->next;
+ }
iseq->compile_data->ensure_node_stack = enl.prev;
break;
}
@@ -3590,6 +3635,10 @@
ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_vid));
ADD_INSN1(ret, nd_line(node), setinlinecache, lstart);
ADD_LABEL(ret, lend);
+
+ if(poped){
+ ADD_INSN(ret, nd_line(node), pop);
+ }
break;
}
case NODE_CVAR:{
@@ -4112,10 +4161,10 @@
iseq->compile_data->start_label = next_label;
iseq->compile_data->redo_label = redo_label;
- ADD_LABEL (ret, redo_label);
- COMPILE_POPED(ret, "optblock body", node->nd_head);
- ADD_LABEL (ret, next_label);
- ADD_INSN (ret, 0, opt_checkenv);
+ ADD_LABEL(ret, redo_label);
+ COMPILE_ (ret, "optblock body", node->nd_head, 1 /* pop */);
+ ADD_LABEL(ret, next_label);
+ ADD_INSN (ret, 0, opt_checkenv);
break;
}
default:
Modified: trunk/disasm.c
===================================================================
--- trunk/disasm.c 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/disasm.c 2005-12-04 19:07:52 UTC (rev 303)
@@ -170,12 +170,12 @@
static char *
catch_type(int type){
switch(type){
- case CATCH_TYPE_RESCUE: return "rs";
- case CATCH_TYPE_ENSURE: return "en";
- case CATCH_TYPE_RETRY: return "rd";
- case CATCH_TYPE_BREAK: return "br";
- case CATCH_TYPE_REDO: return "rd";
- case CATCH_TYPE_NEXT: return "nx";
+ case CATCH_TYPE_RESCUE: return "rescue";
+ case CATCH_TYPE_ENSURE: return "ensure";
+ case CATCH_TYPE_RETRY: return "retry";
+ case CATCH_TYPE_BREAK: return "break";
+ case CATCH_TYPE_REDO: return "redo";
+ case CATCH_TYPE_NEXT: return "next";
default:
rb_bug("unknown catch type (%d)", type);
return 0;
@@ -216,7 +216,7 @@
}
for(i=0; i<iseqdat->catch_table_size; i++){
struct catch_table_entry *entry = &iseqdat->catch_table[i];
- sprintf(buff, "|type: %2s, st: %04d, ed: %04d, sp: %04d, cont: %04d\n",
+ sprintf(buff, "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
catch_type((int)entry->type), (int)entry->start,
(int)entry->end, (int)entry->sp, (int)entry->cont);
rb_str_cat2(str, buff);
Modified: trunk/insns.def
===================================================================
--- trunk/insns.def 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/insns.def 2005-12-04 19:07:52 UTC (rev 303)
@@ -1502,7 +1502,7 @@
{
#if IGNORE_OPTIMIZE
if(reg_cfp->sp != reg_cfp->bp){
- rb_bug("stack error (sp: %p, bp: %p)",
+ rb_bug("Stack consistency error (sp: %p, bp: %p)",
reg_cfp->sp, reg_cfp->bp);
}
#endif
Modified: trunk/test.rb
===================================================================
--- trunk/test.rb 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/test.rb 2005-12-04 19:07:52 UTC (rev 303)
@@ -1,3 +1,94 @@
+
+
+__END__
+begin
+ while true
+ begin
+ break
+ ensure
+ p :ensure
+ raise
+ end
+ end
+rescue
+end
+__END__
+
+begin
+ (1..2).each do
+ begin
+ break
+ ensure
+ p :ensure
+ raise
+ end
+ end
+rescue Exception
+ p :rescue
+end
+
+__END__
+
+ary = [1, 2, 3]
+ary.each{
+ begin
+ break
+ ensure
+ raise
+ end
+}
+
+__END__
+begin
+ [1,2].each do
+ p 1
+ begin
+ break
+ ensure
+ raise StandardError
+ end
+ end
+rescue
+
+end
+__END__
+
+[1,[2, :b],3].each{|e, f|
+ p [e, f]
+}
+
+__END__
+3.times{
+ class C
+ next
+ end
+}
+__END__
+
+C=1
+i=0
+while i<2
+ i+=1
+ C
+end
+__END__
+1.times{
+ C
+# p 1
+}
+__END__
+class C
+ Const = :ok
+ def m
+ 1.times{
+ Const
+ p 1
+ }
+ end
+end
+C.new.m
+__END__
+
3.times{|e|
p e
}
Modified: trunk/vm.c
===================================================================
--- trunk/vm.c 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/vm.c 2005-12-04 19:07:52 UTC (rev 303)
@@ -1327,7 +1327,7 @@
cfp->pc = cfp->iseq->iseq_encoded + entry->cont;
cfp->sp = cfp->bp + entry->sp;
- if(state != TAG_REDO && escape_dfp){
+ if(state != TAG_REDO && state != TAG_NEXT && escape_dfp){
#if OPT_STACK_CACHING
initial = (GET_THROWOBJ_VAL(err));
#else
Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/yarvcore.h 2005-12-04 19:07:52 UTC (rev 303)
@@ -164,10 +164,7 @@
char *buff;
};
-struct iseq_compile_data_ensure_node_stack{
- NODE* ensure_node;
- struct iseq_compile_data_ensure_node_stack *prev;
-};
+struct iseq_compile_data_ensure_node_stack;
struct iseq_compile_data{
/* GC is needed */
Modified: trunk/yarvtest/test_flow.rb
===================================================================
--- trunk/yarvtest/test_flow.rb 2005-12-03 13:28:33 UTC (rev 302)
+++ trunk/yarvtest/test_flow.rb 2005-12-04 19:07:52 UTC (rev 303)
@@ -28,11 +28,11 @@
src = src.gsub(/(\n|$)/) { "; $a << #{cnt+=1}\n" }
src = "$a = []; begin; #{src}; rescue Exception; $a << 99; end; $a"
- if false#true
- puts
- puts '#----'
- puts src
- puts '#----'
+ if false#||true
+ STDERR.puts
+ STDERR.puts '#----'
+ STDERR.puts src
+ STDERR.puts '#----'
end
ae(src)
@@ -375,6 +375,24 @@
end
end
}
+ ae_flow %q{
+ while true
+ begin
+ break
+ ensure
+ break
+ end
+ end
+ }
+ ae_flow %q{
+ while true
+ begin
+ break
+ ensure
+ raise
+ end
+ end
+ }
end
def test_jump_from_class
@@ -426,6 +444,15 @@
end
end
}
+ ae_flow %q{
+ i=0
+ while i<3
+ i+=1
+ class C
+ next 10
+ end
+ end
+ }
end
end
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml