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

yarv-diff:61

From: ko1 atdot.net
Date: 30 Jul 2005 12:26:03 -0000
Subject: [yarv-diff:61] r216 - in trunk: . test

Author: ko1
Date: 2005-07-30 21:26:02 +0900 (Sat, 30 Jul 2005)
New Revision: 216

Added:
   trunk/test/test_flow.rb
Modified:
   trunk/ChangeLog
   trunk/compile.c
   trunk/insns.def
   trunk/test.rb
   trunk/test/test_jump.rb
   trunk/test/yarvtest.rb
   trunk/vm.c
   trunk/vm.h
   trunk/vm_macro.def
   trunk/yarv.h
   trunk/yarvcore.h
Log:
	* yarvcore.h : struct iseq_compile_data_ensure_node_stack is added

	* compile.c : insert ensure clause before break/next/redo

	* vm.c : fix return/break handling

	* yarv.h, vm.c : fix lightweight yield

	* vm.c, insns.def, vm_macro.def : change arguments of th_set_env (add sp)

	* test/test_flow.rb : added

	* test/yarvtest.rb : add ae_flow

	* compile.c, vm_macro.def : add tail-call/tail-recursion optimization
	(experimental)



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/ChangeLog	2005-07-30 12:26:02 UTC (rev 216)
@@ -4,6 +4,26 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-07-30(Sat) 04:44:33 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* yarvcore.h : struct iseq_compile_data_ensure_node_stack is added
+
+	* compile.c : insert ensure clause before break/next/redo
+
+	* vm.c : fix return/break handling
+
+	* yarv.h, vm.c : fix lightweight yield
+
+	* vm.c, insns.def, vm_macro.def : change arguments of th_set_env (add sp)
+
+	* test/test_flow.rb : added
+
+	* test/yarvtest.rb : add ae_flow
+
+	* compile.c, vm_macro.def : add tail-call/tail-recursion optimization
+	(experimental)
+
+
 2005-07-29(Fri) 20:14:11 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* compile.c : make_name_for_block and make_name_with_str

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/compile.c	2005-07-30 12:26:02 UTC (rev 216)
@@ -433,6 +433,23 @@
   verify_list("append", anc1);
 }
 
+#if 0
+/*
+ * anc1: e1, e2, e3
+ * anc2: e4, e5
+ *#=>
+ * anc1: e4, e5
+ * anc2: e1, e2, e3
+ */
+static void SWAP_LIST(LINK_ANCHOR *anc1, LINK_ANCHOR *anc2){
+  LINK_ANCHOR tmp = *anc2;
+  *anc2 = *anc1;
+  *anc1 = tmp;
+  verify_list("swap1", anc1);
+  verify_list("swap2", anc2);
+}
+#endif
+
 static LINK_ANCHOR *REVERSE_LIST(LINK_ANCHOR *anc){
   LINK_ELEMENT *first, *last, *elem, *e;
   first = &anc->anchor;
@@ -1263,6 +1280,17 @@
           }
         }
       }
+
+      if(iobj->insn_id == BIN(end)){
+        INSN *piobj = (INSN*)get_prev_insn((INSN*)list);
+        if(piobj->insn_id == BIN(send)){
+          /* TODO: tail call optimization */
+          if(piobj->operands[2] == 0){
+            //piobj->operands[3] = INT2FIX(FIX2INT(piobj->operands[3]) | VM_CALL_TAILCALL_BIT);
+            //piobj->operands[3] = INT2FIX(FIX2INT(piobj->operands[3]) | VM_CALL_TAILRECURSION_BIT);
+          }
+        }
+      }
     }
     list = list->next;
   }
@@ -1803,6 +1831,22 @@
 }
 
 
+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;
+  DECL_ANCHOR(ensure);
+
+  while(enlp){
+    DECL_ANCHOR(ensure_part);
+    LINK_ANCHOR *t;
+    COMPILE_POPED(ensure_part, "ensure part", enlp->ensure_node);
+
+    ADD_SEQ(ensure, ensure_part);
+    enlp = enlp->prev;
+  }
+  ADD_SEQ(ret, ensure);
+}
+
 /**
   compile each node
 
@@ -2032,11 +2076,12 @@
   }
   case NODE_WHILE:
   case NODE_UNTIL:{
-    LABEL *prev_start_label = iseqobj->compile_data->start_label;
-    LABEL * prev_end_label   = iseqobj->compile_data->end_label;
-    LABEL * prev_redo_label  = iseqobj->compile_data->redo_label;
+    LABEL *prev_start_label   = iseqobj->compile_data->start_label;
+    LABEL *prev_end_label     = iseqobj->compile_data->end_label;
+    LABEL *prev_redo_label    = iseqobj->compile_data->redo_label;
     VALUE prev_loopval_popped = iseqobj->compile_data->loopval_popped;
-    
+    struct iseq_compile_data_ensure_node_stack *enlp = iseqobj->compile_data->ensure_node_stack;
+
     LABEL * next_label  = iseqobj->compile_data->start_label =
       NEW_LABEL(nd_line(node)); /* next  */
     LABEL * redo_label  = iseqobj->compile_data->redo_label  =
@@ -2046,12 +2091,13 @@
     LABEL * end_label = NEW_LABEL(nd_line(node));
 
     iseqobj->compile_data->loopval_popped = poped;
-    
+    iseqobj->compile_data->ensure_node_stack = 0;
+
     ADD_INSNL(ret, nd_line(node), jump, next_label);
 
     ADD_LABEL(ret, redo_label);
     COMPILE_ (ret, "while body", node->nd_body, 1);
-    
+
     ADD_LABEL(ret, next_label); /* next */
     if(type == NODE_WHILE){
       compile_branch_condition(self, iseqobj, ret,
@@ -2068,11 +2114,12 @@
       ADD_INSN(ret, nd_line(node), putnil);
     }
     ADD_LABEL(ret, break_label); /* braek */
-    
+
     iseqobj->compile_data->start_label = prev_start_label;
     iseqobj->compile_data->end_label   = prev_end_label;
     iseqobj->compile_data->redo_label  = prev_redo_label;
     iseqobj->compile_data->loopval_popped = prev_loopval_popped;
+    iseqobj->compile_data->ensure_node_stack = enlp;
     break;
   }
   case NODE_ITER:
@@ -2105,17 +2152,32 @@
   }
   case NODE_BREAK:{
     if(iseqobj->compile_data->redo_label != 0){
+    break_in_loop:
       /* while/until */
       COMPILE_(ret, "break val(while/until)", node->nd_stts,
                iseqobj->compile_data->loopval_popped);
+      add_ensure_iseq(ret, iseqobj, self);
       ADD_INSNL(ret, nd_line(node), jump, iseqobj->compile_data->end_label);
     }
     else if(iseqobj->type == ISEQ_TYPE_BLOCK){
+    break_in_block:
       /* escape from block */
       COMPILE(ret, "break val(block)", node->nd_stts);
       ADD_INSN1(ret, nd_line(node), throw, I2F(0x02) /* TAG_BREAK */);
     }
     else{
+      yarv_iseq_t *ip = iseqobj->parent_iseqobj;
+      while(ip){
+        if(ip->type == ISEQ_TYPE_BLOCK){
+          rb_bug("break in rescue/ensure is not supported");
+          goto break_in_block;
+        }
+        else if(ip->compile_data->redo_label != 0){
+          rb_bug("break in while/until is not supported");
+          goto break_in_loop;
+        }
+        ip = iseqobj->parent_iseqobj;
+      }
       COMPILE_ERROR(("can't put break"));
     }
 
@@ -2123,25 +2185,48 @@
   }
   case NODE_NEXT:{
     if(iseqobj->compile_data->redo_label != 0){
+      add_ensure_iseq(ret, iseqobj, self);
       ADD_INSNL(ret, nd_line(node), jump, iseqobj->compile_data->start_label);
     }
     else if(iseqobj->compile_data->end_label){
       COMPILE(ret, "next val", node->nd_stts);
+      add_ensure_iseq(ret, iseqobj, self);
       ADD_INSNL(ret, nd_line(node), jump, iseqobj->compile_data->end_label);
     }
     else{
+      yarv_iseq_t *ip = iseqobj->parent_iseqobj;
+      while(ip){
+        if(ip->type == ISEQ_TYPE_BLOCK){
+          rb_bug("next in rescue/ensure is not supported");
+        }
+        else if(ip->compile_data->redo_label != 0){
+          rb_bug("next in while/until is not supported");
+        }
+        ip = iseqobj->parent_iseqobj;
+      }
       COMPILE_ERROR(("can't next"));
     }
     break;
   }
   case NODE_REDO:{
     if(iseqobj->compile_data->redo_label){
+      add_ensure_iseq(ret, iseqobj, self);
       ADD_INSNL(ret, nd_line(node), jump, iseqobj->compile_data->redo_label);
     }
     else if(iseqobj->compile_data->start_label){
       ADD_INSNL(ret, nd_line(node), jump, iseqobj->compile_data->start_label);
     }
     else{
+      yarv_iseq_t *ip = iseqobj->parent_iseqobj;
+      while(ip){
+        if(ip->type == ISEQ_TYPE_BLOCK){
+          rb_bug("redo in rescue/ensure is not supported");
+        }
+        else if(ip->compile_data->redo_label != 0){
+          rb_bug("redo in while/until is not supported");
+        }
+        ip = iseqobj->parent_iseqobj;
+      }
       COMPILE_ERROR(("can't redo"));
     }
     break;
@@ -2219,15 +2304,20 @@
     break;
   }
   case NODE_ENSURE:{
+    DECL_ANCHOR(ensr);
     VALUE ensure = NEW_CHILD_ISEQOBJ(node->nd_ensr, rb_str_new2("ensure"),
                                      self, ISEQ_TYPE_ENSURE);
     LABEL * lstart = NEW_LABEL(nd_line(node));
     LABEL * lend   = NEW_LABEL(nd_line(node));
     LABEL * lcont  = NEW_LABEL(nd_line(node));
-    DECL_ANCHOR(ensr);
-    
     VALUE prev_in_ensure = iseqobj->compile_data->in_ensure;
+    struct iseq_compile_data_ensure_node_stack enl = {
+      node->nd_ensr,
+      iseqobj->compile_data->ensure_node_stack /* prev */
+    };
+
     iseqobj->compile_data->in_ensure = Qtrue;
+    iseqobj->compile_data->ensure_node_stack = &enl;
 
     COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr);
     
@@ -2244,6 +2334,7 @@
 
     iseqobj->compile_data->in_ensure = prev_in_ensure;
     ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, lstart, lend, ensure, 0, lcont);
+    iseqobj->compile_data->ensure_node_stack = enl.prev;
     break;
   }
     

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/insns.def	2005-07-30 12:26:02 UTC (rev 216)
@@ -951,7 +951,7 @@
   GetISeqVal(klass_iseqval, klass_iseq);
   th_set_env(th, klass_iseq,
              FRAME_MAGIC_CLASS, klass, 0,
-             klass_iseq->ISEQ_MEMBER, 0,
+             klass_iseq->ISEQ_MEMBER, GET_SP(), 0,
              klass_iseq->local_size, 0, 0);
   RESTORE_REGS();
   
@@ -1013,7 +1013,7 @@
   GetISeqVal(module_iseqval, module_iseq);
   th_set_env(th, module_iseq,
              FRAME_MAGIC_CLASS, module, 0,
-             module_iseq->ISEQ_MEMBER, 0,
+             module_iseq->ISEQ_MEMBER, GET_SP(), 0,
              module_iseq->local_size, 0, 0);
   RESTORE_REGS();
   
@@ -1209,7 +1209,7 @@
     }
     th_set_env(th, iseq,
                FRAME_MAGIC_BLOCK, block->self, (VALUE)block->dfp,
-               iseq->ISEQ_MEMBER, block->lfp,
+               iseq->ISEQ_MEMBER, GET_SP(), block->lfp,
                iseq->local_size - argc, 0, 0);
     reg_cfp->sp -= argc;
     RESTORE_REGS();

Added: trunk/test/test_flow.rb
===================================================================
--- trunk/test/test_flow.rb	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/test/test_flow.rb	2005-07-30 12:26:02 UTC (rev 216)
@@ -0,0 +1,229 @@
+#
+# This test program is contributed by   George Marrows
+# Re: [Yarv-devel] Some tests	for test_jump.rb
+#
+
+require 'test/yarvtest'
+
+class TestFlow < YarvTestBase
+  
+  def test_while_with_ensure
+    ae %q{
+      a = []
+      i = 0
+      begin
+        while i < 1
+          i+=1
+          begin
+            begin
+              next
+            ensure
+              a << :ok
+            end
+          ensure
+            a << :ok2
+          end
+        end
+      ensure
+        a << :last
+      end
+    }
+    ae %q{
+      a = []
+      i = 0
+      begin
+        while i < 1
+          i+=1
+          begin
+            begin
+              break
+            ensure
+              a << :ok
+            end
+          ensure
+            a << :ok2
+          end
+        end
+      ensure
+        a << :last
+      end
+    }
+    ae %q{
+      a = []
+      i = 0
+      begin
+        while i < 1
+          if i>0
+            break
+          end
+          i+=1
+          begin
+            begin
+              redo
+            ensure
+              a << :ok
+            end
+          ensure
+            a << :ok2
+          end
+        end
+      ensure
+        a << :last
+      end
+   }
+  end
+  
+  def test_ensure_normal_flow
+    ae_flow %{ 
+      begin
+      ensure
+      end }
+  end
+
+  def test_ensure_exception
+    ae_flow %{
+      begin
+        raise StandardError
+      ensure
+      end
+    }
+  end
+
+  def test_break_in_block_runs_ensure
+    ae_flow %{ 
+      [1,2].each do
+        begin
+          break
+        ensure
+        end
+      end
+    }
+  end
+
+  def test_next_in_block_runs_ensure
+    ae_flow %{ 
+      [1,2].each do
+        begin
+          next
+        ensure
+        end
+      end
+    }
+  end
+  def test_return_from_method_runs_ensure
+    ae_flow %{ 
+      o = "test"
+      def o.test(a)
+        return a
+      ensure
+      end
+      o.test(123)
+    }
+  end
+
+  def test_break_ensure_interaction1
+    # make sure that any 'break state' set up in the VM is c
+    # the time of the ensure
+    ae_flow %{ 
+      [1,2].each{
+        break
+      }
+      begin
+      ensure
+      end
+    }
+  end
+  
+  def test_break_ensure_interaction2
+    # ditto, different arrangement
+    ae_flow %{ 
+      begin
+        [1,2].each do
+          break
+        end
+      ensure
+      end
+    }
+  end
+  
+  def test_break_through_2_ensures
+    ae_flow %{ 
+      [1,2].each do
+        begin
+          begin
+            break
+          ensure
+          end
+        ensure
+        end
+      end
+    }
+  end
+  
+  def test_ensure_break_ensure
+    # break through an ensure; run 2nd normally
+    ae_flow %{ 
+      begin
+        [1,2].each do
+          begin
+            break
+          ensure
+          end
+        end
+      ensure
+      end
+    }
+  end
+  
+  def test_exception_overrides_break
+    ae_flow %{ 
+      [1,2].each do
+        begin
+          break
+        ensure
+          raise StandardError
+        end
+      end
+    }
+  end
+
+if false
+  # unsupported
+  def test_break_in_exception
+    ae_flow %q{
+      i=0
+      while i<3
+        i+=1
+        begin
+        ensure
+          next
+        end
+      end
+    }
+    ae_flow %q{
+      i=0
+      while i<3
+        i+=1
+        begin
+          raise
+        rescue
+          next
+        end
+      end
+    }
+  end
+  
+  def test_break_overrides_exception
+    ae_flow %{ 
+      [1,2].each do
+        begin
+          raise StandardError
+        ensure
+          break
+        end
+      end
+    }
+  end
+end
+end
+

Modified: trunk/test/test_jump.rb
===================================================================
--- trunk/test/test_jump.rb	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/test/test_jump.rb	2005-07-30 12:26:02 UTC (rev 216)
@@ -215,6 +215,14 @@
       m
     }
   end
+
+  def test_break_from_times
+    ae %q{
+      3.times{
+        break :ok
+      }
+    }
+  end
   
 end
 

Modified: trunk/test/yarvtest.rb
===================================================================
--- trunk/test/yarvtest.rb	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/test/yarvtest.rb	2005-07-30 12:26:02 UTC (rev 216)
@@ -26,7 +26,40 @@
 
     assert_equal(ruby, yarv)
   end
-
+  
+  def ae_flow(src, for_value=true)
+    # Tracks flow through the code
+    # A test like
+    #   begin
+    #   ensure
+    #   end
+    # gets transformed into
+    #   a = []
+    #   begin
+    #     begin; a << 1
+    #     ensure; a << 2
+    #     end; a << 3
+    #   rescue Exception
+    #     a << 99
+    #   end
+    #   a
+    # before being run. This tracks control flow through the code.
+    
+    cnt = 0
+    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 '#----'
+    end
+    
+    ae(src)
+  end
+  
+  
   def test_
   end
 

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/test.rb	2005-07-30 12:26:02 UTC (rev 216)
@@ -8,137 +8,69 @@
 ###########################################################
 $prog =<<'__EOP__'
 
-3.times{|i|
-  p i
-}
-
-__END__
-def m
-3.times{
-  4.times{
-    5.times{
-      return caller 0
-    }
-  }
-}
+def m1 a
+  if a == 0
+  else
+    m1 a-1
+  end
 end
 
-m
+m1 3
 
-__END__
-def m
-  1.times{
-    raise
-  }
-end
+p 1
 
-def iter
-  yield
-end
-
-begin
-  m
-rescue => e
-  p e
-  p e.backtrace
-end
-
-
-
 __END__
-def m
-  begin
-    raise
-  rescue => e
-    p e.backtrace
+def m n
+  if n == 0
+    #
+  else
+    m n-1
   end
 end
 
-def mm
-  caller 0
-end
+m 5
+p 1
 
+__END__
+
 def iter
   yield
 end
 
 begin
   iter{
-    raise
+    iter{
+      iter{
+        raise
+      }
+    }
   }
 rescue => e
-  e.backtrace
+  puts e.backtrace
 end
 
-
 __END__
 
-3.times{|bl|
-  break 10
-}
-
-
-__END__
-      def fact(n)
-        if(n > 1)
-          n * fact(n-1)
-        else
-          1
-        end
-      end
-      fact(300)
-__END__
-if true  then
-  
-elsif true
-then
-  1
-end
-
-__END__
-
-def proc(&pr)
-  pr
-end
-
-def m
-  a = 1
-  m2{
-    a
+def m enum
+  enum.map{
+    yield
   }
 end
 
-def m2
-  b = 2
-  proc{
-    [yield, b]
+begin
+  m(1..3){
+    raise
   }
-  100000.times{|x|
-    "#{x}"
-  }
-  3.times{
-    3.times{
-      3.times{
-      }
-    }
-  }
-  yield
+rescue => e
+  puts e.backtrace
 end
-m
-
 __END__
+while true
+  class C
+    break
+  end
+end
 
-pr = m
-x = ['a', 1,2,3,4,5,6,7,8,9,0,
-          1,2,3,4,5,6,7,8,9,0,
-          1,2,3,4,5,6,7,8,9,0,
-          1,2,3,4,5,6,7,8,9,0,
-          1,2,3,4,5,6,7,8,9,0,
-    ]
-    100000.times{|i|
-      "#{i}"
-    }
-    pr.call
 __EOP__
 ###########################################################
 

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/vm.c	2005-07-30 12:26:02 UTC (rev 216)
@@ -63,10 +63,8 @@
 static inline
 VALUE th_set_env(yarv_thread_t *th, yarv_iseq_t *iseq,
                  VALUE magic, VALUE self, VALUE specval,
-                 VALUE *pc, VALUE *lfp,
+                 VALUE *pc, VALUE *sp, VALUE *lfp,
                  int local_size, int argc, const VALUE *argv){
-  
-  VALUE *sp = th->cfp->sp;
   VALUE *dfp;
   int i;
  
@@ -105,7 +103,7 @@
 VALUE th_set_finish_env(yarv_thread_t *th){
   th_set_env(th, 0,
              FRAME_MAGIC_FINISH, Qnil, 0,
-             0, 0,
+             0, th->cfp->sp, 0,
              0, 0, 0);
   
   th->cfp->pc = &yarv_finish_insn_seq[0];
@@ -127,7 +125,7 @@
   
   return th_set_env(th, iseq, 
                     FRAME_MAGIC_TOP, ruby_top_self, 0,
-                    iseq->ISEQ_MEMBER, 0,
+                    iseq->ISEQ_MEMBER, th->cfp->sp, 0,
                     iseq->local_size, 0, 0);
 }
 
@@ -248,6 +246,7 @@
   case YARV_METHOD_NODE:{
     yarv_control_frame_t *reg_cfp;
     int i;
+    const int flag = 0;
     
     th_set_finish_env(th);
     reg_cfp = th->cfp;
@@ -265,7 +264,7 @@
     struct cmethod_info cmi = {0, id, klass};
     th_set_env(th, (yarv_iseq_t *)&cmi,
                FRAME_MAGIC_CFUNC, recv, (VALUE)blockptr,
-               0, 0,
+               0, reg_cfp->sp, 0,
                0, 0, 0);
 
     val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
@@ -347,7 +346,8 @@
 
   th_set_env(th, 0,
              FRAME_MAGIC_IFUNC, block->self, (VALUE)block->dfp,
-             0, block->lfp, 0, 0, 0);
+             0, th->cfp->sp, block->lfp,
+             0, 0, 0);
 
   val = (*ifunc->nd_cfnc)(arg, ifunc->nd_tval, Qnil);
   
@@ -369,7 +369,7 @@
       th_set_finish_env(th);
       th_set_env(th, block->iseq, FRAME_MAGIC_BLOCK,
                  block->self, GC_GUARDED_PTR(block->dfp),
-                 block->iseq->ISEQ_MEMBER, block->lfp,
+                 block->iseq->ISEQ_MEMBER, th->cfp->sp, block->lfp,
                  block->iseq->local_size, argc, argv);
       val = th_eval_body(th);
     }
@@ -398,15 +398,23 @@
   }
   else{
     if(BUILTIN_TYPE(block->iseq) != T_NODE){
+      int local_size = block->iseq->local_size;
       th_set_finish_env(th);
+
+      if(block->iseq->argc < argc){
+        argc = block->iseq->argc;
+      }
+
       th_set_env(th, block->iseq, FRAME_MAGIC_BLOCK,
                  block->self, GC_GUARDED_PTR(block->dfp),
-                 block->iseq->ISEQ_MEMBER, block->lfp,
-                 block->iseq->local_size, argc, argv);
+                 block->iseq->ISEQ_MEMBER, th->cfp->sp, block->lfp,
+                 local_size, argc, argv);
 
       data->local_size = block->iseq->local_size;
       data->pc = block->iseq->ISEQ_MEMBER;
       data->sp = th->cfp->sp;
+      data->argc = argc;
+      
       th->cfp+=2; // pop, pop
     }
     else{
@@ -429,7 +437,7 @@
     th->cfp->pc = data->pc;
     // th->cfp->sp = data->sp;
     
-    for(i=0; i<argc; i++){
+    for(i=0; i<data->argc; i++){
       th->cfp->dfp[i - data->local_size] = argv[i];
     }
 
@@ -447,7 +455,7 @@
   th_set_finish_env(th);
   th_set_env(th, proc->block.iseq,
              FRAME_MAGIC_PROC, proc->block.self, (VALUE)proc->block.dfp,
-             proc->block.iseq->ISEQ_MEMBER, proc->block.lfp,
+             proc->block.iseq->ISEQ_MEMBER, th->cfp->sp, proc->block.lfp,
              proc->block.iseq->local_size, argc, argv);
 
   //proc_dump_raw(proc);
@@ -1007,6 +1015,31 @@
     cfp = th->cfp;
     epc = cfp->pc - cfp->iseq->ISEQ_MEMBER;
 
+    if(state == TAG_BREAK || state == TAG_RETURN){
+      static VALUE  *escape_dfp;
+      escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
+
+      // printf("%p, %p\n", escape_dfp, cfp->dfp);
+
+      if(cfp->dfp == escape_dfp){
+        if(state == TAG_RETURN){
+          SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp+1)->dfp);
+          SET_THROWOBJ_STATE      (err, state = TAG_BREAK);
+          /* through */
+        }
+        else{
+          /* TAG_BREAK */
+#if OPT_STACK_CACHING
+          initial = (GET_THROWOBJ_VAL(err));
+#else
+          *th->cfp->sp++ = (GET_THROWOBJ_VAL(err));
+#endif
+          ruby_errinfo = Qnil;
+          goto vm_loop_start;
+        }
+      }
+    }
+    
     for(i=0; i<cfp->iseq->catch_table_size; i++){
       entry = &cfp->iseq->catch_table[i];
       if(entry->start <  epc &&
@@ -1029,7 +1062,6 @@
                 entry->type == CATCH_TYPE_RETRY){
           VALUE  *escape_dfp;
           escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
-          // printf("[%d, %d]\n", GET_DFP() - th->stack, escape_dfp - th->stack);
           
           if(cfp->dfp == escape_dfp){
             cfp->pc = cfp->iseq->ISEQ_MEMBER + entry->cont;
@@ -1055,7 +1087,7 @@
       /* push block frame */
       th_set_env(th, catch_iseq,
                  FRAME_MAGIC_BLOCK, cfp->self, GC_GUARDED_PTR(cfp->dfp),
-                 catch_iseq->ISEQ_MEMBER, cfp->lfp,
+                 catch_iseq->ISEQ_MEMBER, cfp->sp, cfp->lfp,
                  catch_iseq->local_size - 1, 0, 0);
 
       state = 0;
@@ -1063,34 +1095,6 @@
       goto vm_loop_start;
     }
     else{
-      yarv_iseq_t  *iseq;
-     
-      if(state == TAG_BREAK || state == TAG_RETURN){
-        static VALUE  *escape_dfp;
-        escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
-
-        // printf("%p, %p\n", escape_dfp, cfp->dfp);
-        
-        if(cfp->dfp == escape_dfp){
-          if(state == TAG_RETURN){
-            SET_THROWOBJ_CATCH_POINT(err, (VALUE)(cfp+1)->dfp);
-            SET_THROWOBJ_STATE      (err, state = TAG_BREAK);
-            /* through */
-          }
-          else{
-            /* TAG_BREAK */
-#if OPT_STACK_CACHING
-            initial = (GET_THROWOBJ_VAL(err));
-#else
-            *th->cfp->sp++ = (GET_THROWOBJ_VAL(err));
-#endif
-            ruby_errinfo = Qnil;
-            goto vm_loop_start;
-          }
-        }
-      }
-
-    rewind_stack_point:
       th->cfp++;
       if(th->cfp->pc != &yarv_finish_insn_seq[0]){
         goto exception_handler;

Modified: trunk/vm.h
===================================================================
--- trunk/vm.h	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/vm.h	2005-07-30 12:26:02 UTC (rev 216)
@@ -33,7 +33,7 @@
 
 #if 0
 #undef  VMDEBUG
-#define VMDEBUG 10
+#define VMDEBUG 5
 #endif
 
 // #define COLLECT_USAGE_ANALYSIS

Modified: trunk/vm_macro.def
===================================================================
--- trunk/vm_macro.def	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/vm_macro.def	2005-07-30 12:26:02 UTC (rev 216)
@@ -55,7 +55,7 @@
   
   th_set_env(th, (yarv_iseq_t *)&cmi,
              FRAME_MAGIC_CFUNC, recv, (VALUE)blockptr,
-             0, 0,
+             0, GET_SP(), 0,
              0, 0, 0);
 
   reg_cfp->sp -= num + 1;
@@ -68,7 +68,6 @@
 }
 
 MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num){
-  
   yarv_iseq_t *niseq;
   VALUE *sp = GET_SP();
   int opt_pc = 0, clear_local_size, i;
@@ -160,13 +159,34 @@
 
   {
     VALUE *rsp = reg_cfp->sp - num - 1;
-    reg_cfp->sp = sp;
 
-    th_set_env(th, niseq,
-               FRAME_MAGIC_METHOD, recv, (VALUE)blockptr,
-               niseq->ISEQ_MEMBER + opt_pc, 0,
-               0, 0, 0);
-    reg_cfp->sp = rsp;
+    if(0 &&
+       (flag & VM_CALL_TAILCALL_BIT)){
+      th->cfp++;
+      th_set_env(th, niseq,
+                 FRAME_MAGIC_METHOD, recv, (VALUE)blockptr,
+                 niseq->ISEQ_MEMBER + opt_pc, sp, 0,
+                 0, 0, 0);
+    }
+    else if(0 &&
+            (flag & VM_CALL_TAILRECURSION_BIT) &&
+            niseq == GET_ISEQ()){
+      /* do nothing */
+      GET_CFP()->self = recv;
+      SET_LFP(sp);
+      SET_DFP(sp);
+      *sp++ = (VALUE)blockptr;
+      reg_cfp->sp = sp;
+      reg_cfp->bp = sp;
+      SET_PC(niseq->ISEQ_MEMBER + opt_pc);
+    }
+    else{
+      th_set_env(th, niseq,
+                 FRAME_MAGIC_METHOD, recv, (VALUE)blockptr,
+                 niseq->ISEQ_MEMBER + opt_pc, sp, 0,
+                 0, 0, 0);
+      reg_cfp->sp = rsp;
+    }
     RESTORE_REGS();
   }
 }

Modified: trunk/yarv.h
===================================================================
--- trunk/yarv.h	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/yarv.h	2005-07-30 12:26:02 UTC (rev 216)
@@ -21,6 +21,7 @@
   yarv_block_t *block;
   VALUE *pc;
   VALUE *sp;
+  int argc;
   int local_size;
 };
 

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2005-07-29 11:18:39 UTC (rev 215)
+++ trunk/yarvcore.h	2005-07-30 12:26:02 UTC (rev 216)
@@ -79,6 +79,11 @@
   char *buff;
 };
 
+struct iseq_compile_data_ensure_node_stack{
+  NODE* ensure_node;
+  struct iseq_compile_data_ensure_node_stack *prev;
+};
+
 struct iseq_compile_data{
   /* GC is needed */
   VALUE err_info;
@@ -91,6 +96,8 @@
   VALUE current_block;
   VALUE loopval_popped;  /* used by NODE_BREAK */
   VALUE in_ensure;       /* used by NODE_RETURN */
+  VALUE ensure_node;
+  struct iseq_compile_data_ensure_node_stack *ensure_node_stack;
   int   cached_const;
 
   struct iseq_compile_data_storage *storage_head;
@@ -296,6 +303,7 @@
 #define VM_CALL_ARGS_BLOCKARG_BIT 0x02
                          /* 0x04, 0x08 */
 #define VM_CALL_TAILCALL_BIT      0x10
+#define VM_CALL_TAILRECURSION_BIT      0x20
 
 
 VALUE thread_invoke_proc_call(VALUE self, VALUE proc, int argc, VALUE *args);


--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

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