[前][次][番号順一覧][スレッド一覧][生データ]

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

[前][次][番号順一覧][スレッド一覧][生データ]