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

yarv-diff:176

From: ko1 atdot.net
Date: 28 Dec 2005 06:38:37 -0000
Subject: [yarv-diff:176] r334 - in trunk: . benchmark yarvtest

Author: ko1
Date: 2005-12-28 15:38:36 +0900 (Wed, 28 Dec 2005)
New Revision: 334

Modified:
   trunk/ChangeLog
   trunk/benchmark/bmx_temp.rb
   trunk/compile.c
   trunk/eval.c
   trunk/insns.def
   trunk/test.rb
   trunk/vm.c
   trunk/vm_macro.def
   trunk/yarvtest/test_flow.rb
   trunk/yarvtest/test_method.rb
Log:
	* compile.c : fix calculation of stack_max

	* eval.c (rb_iter) : fix block/retry handling

	* yarvtest/test_flow.rb : add tests for above

	* insns.def : fix block passing on super (super(&nil))

	* vm_macro.def, insns.def : fix convert method of object to array

	* yarvtest/test_method.rb : fix a test for above

	* vm.c : fix backtrace generate algorithm



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/ChangeLog	2005-12-28 06:38:36 UTC (rev 334)
@@ -4,6 +4,23 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-12-28(Wed) 15:31:46 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* compile.c : fix calculation of stack_max
+
+	* eval.c (rb_iter) : fix block/retry handling
+
+	* yarvtest/test_flow.rb : add tests for above
+
+	* insns.def : fix block passing on super (super(&nil))
+
+	* vm_macro.def, insns.def : fix convert method of object to array
+
+	* yarvtest/test_method.rb : fix a test for above
+
+	* vm.c : fix backtrace generate algorithm
+
+
 2005-12-28(Wed) 10:36:45 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* compile.c, compile.h : refactoring (remove self passing, etc)

Modified: trunk/benchmark/bmx_temp.rb
===================================================================
--- trunk/benchmark/bmx_temp.rb	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/benchmark/bmx_temp.rb	2005-12-28 06:38:36 UTC (rev 334)
@@ -1,8 +1,9 @@
-err = RuntimeError.new
-10000000.times{
+i=0
+while i<100000
   begin
-    #raise err
+    raise
   rescue
     
   end
-}
+  i+=1
+end

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/compile.c	2005-12-28 06:38:36 UTC (rev 334)
@@ -1273,6 +1273,9 @@
       }
       else{
         sp = calc_sp_depth(sp, iobj);
+        if(sp > stack_max){
+          stack_max = sp;
+        }
       }
       
       // fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp);
@@ -1282,7 +1285,6 @@
       generated_iseq[pos] = insn;
       types = insn_op_types(insn);
       len   = insn_len(insn);
-      stack_max += insn_ret_num(insn);
 
       /* operand check */
       if(iobj->operand_size != len - 1){
@@ -2091,7 +2093,7 @@
       }
       case NODE_TO_ARY:
         COMPILE  (ret, "rhs to ary", rhsn->nd_head);
-        ADD_INSN2(ret, 0, expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
+        ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
         break;
 
       case NODE_SPLAT:

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/eval.c	2005-12-28 06:38:36 UTC (rev 334)
@@ -1263,7 +1263,7 @@
  */
 
 static VALUE
-rb_f_loop()
+rb_f_loop(void)
 {
     for (;;) {
 	rb_yield_0(Qundef, 0, 0, 0, Qfalse);
@@ -1272,10 +1272,11 @@
     return Qnil;		/* dummy */
 }
 
+#define GET_THROWOBJ_CATCH_POINT(obj) ((VALUE*)RNODE((obj))->u2.value)
+
 VALUE
-rb_iterate(it_proc, data1, bl_proc, data2)
-    VALUE (*it_proc) _((VALUE)), (*bl_proc)(ANYARGS);
-    VALUE data1, data2;
+rb_iterate(VALUE (*it_proc)(VALUE), VALUE data1,
+           VALUE (*bl_proc)(ANYARGS), VALUE data2)
 {
   int state;
   volatile VALUE retval = Qnil;
@@ -1294,17 +1295,28 @@
     }
     retval = (*it_proc)(data1);
   }
-  else if (state == TAG_BREAK /* TODO: more check */ ) {
-    state = 0;
-    th->state = 0;
-    th->errinfo = Qnil;
+  else{
+    VALUE err = th->errinfo;
+    if (state == TAG_BREAK) {
+      VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
+      VALUE *cdfp = (th->cfp+2)->dfp;
+      if(cdfp == escape_dfp){
+        state = 0;
+        th->state = 0;
+        th->errinfo = Qnil;
+      }
+    }
+    else if (state == TAG_RETRY) {
+      VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
+      VALUE *cdfp = (th->cfp+2)->dfp;
+      if(cdfp == escape_dfp){
+        state = 0;
+        th->state = 0;
+        th->errinfo = Qnil;
+        goto iter_retry;
+      }
+    }
   }
-  else if (state == TAG_RETRY) {
-    state = 0;
-    th->state = 0;
-    th->errinfo = Qnil;
-    goto iter_retry;
-  }
   TH_POP_TAG();
 
   switch (state){

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/insns.def	2005-12-28 06:38:36 UTC (rev 334)
@@ -515,42 +515,24 @@
 {
   int i;
   if((long)num >= 0){
-
-    /* TODO: stack overflow check */
-    
-    if(CLASS_OF(ary) == rb_cArray ||
-       CLASS_OF(ary) == rb_cValues){ /* TODO: for compatibility */
-      int len = RARRAY(ary)->len;
-      for(i=0; i<len && i<num; i++){
-        PUSH(RARRAY(ary)->ptr[i]);
-      }
-      for(; i<num; i++){
-        PUSH(Qnil);
-      }
-      if(flag){
-        if(len > num){
-          PUSH(rb_ary_new4(len - num, &RARRAY(ary)->ptr[num]));
-        }
-        else{
-          PUSH(rb_ary_new());
-        }
-      }
+    int len;
+    if(TYPE(ary) != T_ARRAY){
+      ary = rb_ary_to_ary(ary);
     }
-    else{
-      if(num > 0){
-        PUSH(ary);
+    len = RARRAY(ary)->len;
+    for(i=0; i<len && i<num; i++){
+      PUSH(RARRAY(ary)->ptr[i]);
+    }
+    for(; i<num; i++){
+      PUSH(Qnil);
+    }
+    if(flag){
+      if(len > num){
+        PUSH(rb_ary_new4(len - num, &RARRAY(ary)->ptr[num]));
       }
-      for(i=1; i<num; i++){
-        PUSH(Qnil);
+      else{
+        PUSH(rb_ary_new());
       }
-      if(flag){
-        if(num > 0){
-          PUSH(rb_ary_new());
-        }
-        else{
-          PUSH(rb_ary_new3(1, ary));
-        }
-      }
     }
   }
   else{
@@ -608,7 +590,7 @@
 {
   if(flag == Qfalse){
     /* NODE_SPLAT */
-    obj = rb_convert_type(ary, T_ARRAY, "Array", "to_a");
+    obj = rb_Array(ary);
   }
   else{
     /* NODE_SVALUE */
@@ -637,9 +619,11 @@
 {
   int i;
   result = Qfalse;
+
   if(TYPE(ary) != T_ARRAY){
     ary = rb_ary_to_ary(ary);
   }
+
   if(flag == Qtrue){
     /* NODE_CASE */
     for(i=0; i< RARRAY(ary)->len; i++){
@@ -1372,7 +1356,8 @@
   tmp_blockptr = 0;
   macro_eval_setup_send_arguments(tmp_num, tmp_blockptr,
                                   flag, blockiseq);
-  if(!tmp_blockptr){
+  if(!tmp_blockptr &&
+     !(flag & VM_CALL_ARGS_BLOCKARG_BIT)){
     tmp_blockptr = GET_BLOCK_PTR();
   }
   goto LABEL_IS_SC(start_init_in_super);
@@ -1440,8 +1425,7 @@
       if(argc == 1){
         VALUE ary = TOPN(0);
 
-        if(!SPECIAL_CONST_P(ary) &&
-           BUILTIN_TYPE(ary) == T_ARRAY){
+        if(TYPE(ary) == T_ARRAY){
           int i;
           INC_SP(-1);
           argc = 0;

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/test.rb	2005-12-28 06:38:36 UTC (rev 334)
@@ -1,178 +1,468 @@
+require 'test/unit'
+class Array
+  def iter_test1
+    collect{|e| [e, yield(e)]}.sort{|a,b|a[1]<=>b[1]}
+  end
+  def iter_test2
+    a = collect{|e| [e, yield(e)]}
+    a.sort{|a,b|a[1]<=>b[1]}
+  end
+end
 
-at_exit{
-  break
-}
+class TestIterator < Test::Unit::TestCase
+  def ttt
+    assert(iterator?)
+  end
+  def test_iterator
+    assert(!iterator?)
 
-__END__
+    ttt{}
 
-Const = :top
-C = Class.new{
-  def m
-    p "C#m"
+    # yield at top level	!! here's not toplevel
+    assert(!defined?(yield))
   end
-}
 
-p C.instance_methods(false)
-C.new.m
+  def test_array
+    $x = [1, 2, 3, 4]
+    $y = []
 
-__END__
+    # iterator over array
+    for i in $x
+      $y.push i
+    end
+    assert_equal($x, $y)
+  end
 
-class C
-  a = 10
-  1.times{
-    a = 10
-    b = 20
-  }
-end
-__END__
+  def tt
+    1.upto(10) {|i|
+      yield i
+    }
+  end
 
-def m a
-  1.times{
-    b = 1
-    a = 20
-  }
-end
+  def tt2(dummy)
+    yield 1
+  end
 
+  def tt3(&block)
+    tt2(raise(ArgumentError,""),&block)
+  end
 
-__END__
+  def test_nested_iterator
+    i = 0
+    tt{|i| break if i == 5}
+    assert_equal(5, i)
 
-def m
-  p :m
-end
+    assert_raises(ArgumentError) do
+      tt3{}
+    end
+  end
 
-2.times{
-  m()
-  Object.class_eval{
-    p self
-    remove_method :m
-  }
-}
-__END__
-class A
-  C = "BAD"
-  class B
-    def self.c
-      C
+  def tt4 &block
+    tt2(raise(ArgumentError,""),&block)
+  end
+
+  def test_block_argument_without_paren
+    assert_raises(ArgumentError) do
+      tt4{}
     end
   end
-end
 
-A::B.c   # cache
-A::B.const_set :C, "OK"
-p A::B.c
+  # iterator break/redo/next/retry
+  def test_break
+    done = true
+    loop{
+      break
+      done = false			# should not reach here
+    }
+    assert(done)
 
-__END__
-p [0][*0]
+    done = false
+    $bad = false
+    loop {
+      break if done
+      done = true
+      next
+      $bad = true			# should not reach here
+    }
+    assert(!$bad)
 
-__END__
+    done = false
+    $bad = false
+    loop {
+      break if done
+      done = true
+      redo
+      $bad = true			# should not reach here
+    }
+    assert(!$bad)
 
-def m *args
-  args
-end
+    $x = []
+    for i in 1 .. 7
+      $x.push i
+    end
+    assert_equal(7, $x.size)
+    assert_equal([1, 2, 3, 4, 5, 6, 7], $x)
 
-m(*1)
-__END__
-
-class C
-        def m *args
-          "C#m(#{args.join(',')})"
-        end
-        def b
-          class << self
-            define_method(:m){|a, b|
-              1.times{
-                p super
-              }
-            }
-          end
-          self
-        end
+    $done = false
+    $x = []
+    for i in 1 .. 7			# see how retry works in iterator loop
+      if i == 4 and not $done
+	$done = true
+	retry
       end
-      C.new.b.m(:ok1, :ok2)
+      $x.push(i)
+    end
+    assert_equal(10, $x.size)
+    assert_equal([1, 2, 3, 1, 2, 3, 4, 5, 6, 7], $x)
+  end
 
-__END__
+  def test_append_method_to_built_in_class
+    $x = [[1,2],[3,4],[5,6]]
+    assert_equal($x.iter_test1{|x|x}, $x.iter_test2{|x|x})
+  end
 
-class X
-  def a
-  end
-  def b
-    class << self
-      define_method(:a) {
-        super
-      }
+  class IterTest
+    def initialize(e); @body = e; end
+
+    def each0(&block); @body.each(&block); end
+    def each1(&block); @body.each {|*x| block.call(*x) } end
+    def each2(&block); @body.each {|*x| block.call(x) } end
+    def each3(&block); @body.each {|x| block.call(*x) } end
+    def each4(&block); @body.each {|x| block.call(x) } end
+    def each5; @body.each {|*x| yield(*x) } end
+    def each6; @body.each {|*x| yield(x) } end
+    def each7; @body.each {|x| yield(*x) } end
+    def each8; @body.each {|x| yield(x) } end
+
+    def f(a)
+      a
     end
   end
-end
 
-x = X.new
-x.b
-x.a
-__END__
-class Module
-  public :remove_const
-end
+  def test_itertest
+    assert_equal([1], IterTest.new(nil).method(:f).to_proc.call([1]))
+    m = /\w+/.match("abc")
+    assert_equal([m], IterTest.new(nil).method(:f).to_proc.call([m]))
 
-class A
-  C = "OK"
-  class B
-    C = "BAD"
-    def self.c
-      C
+    IterTest.new([0]).each0 {|x| assert_equal(0, x)}
+    IterTest.new([1]).each1 {|x| assert_equal(1, x)}
+    IterTest.new([2]).each2 {|x| assert_equal([2], x)}
+    IterTest.new([4]).each4 {|x| assert_equal(4, x)}
+    IterTest.new([5]).each5 {|x| assert_equal(5, x)}
+    IterTest.new([6]).each6 {|x| assert_equal([6], x)}
+    IterTest.new([8]).each8 {|x| assert_equal(8, x)}
+
+    IterTest.new([[0]]).each0 {|x| assert_equal([0], x)}
+    IterTest.new([[1]]).each1 {|x| assert_equal([1], x)}
+    IterTest.new([[2]]).each2 {|x| assert_equal([[2]], x)}
+    IterTest.new([[3]]).each3 {|x| assert_equal(3, x)}
+    IterTest.new([[4]]).each4 {|x| assert_equal([4], x)}
+    IterTest.new([[5]]).each5 {|x| assert_equal([5], x)}
+    IterTest.new([[6]]).each6 {|x| assert_equal([[6]], x)}
+    IterTest.new([[7]]).each7 {|x| assert_equal(7, x)}
+    IterTest.new([[8]]).each8 {|x| assert_equal([8], x)}
+
+    IterTest.new([[0,0]]).each0 {|x| assert_equal([0,0], x)}
+    IterTest.new([[8,8]]).each8 {|x| assert_equal([8,8], x)}
+  end
+
+  def m(var)
+    var
+  end
+
+  def m1
+    m(block_given?)
+  end
+
+  def m2
+    m(block_given?,&proc{})
+  end
+
+  def test_block_given
+    assert(m1{p 'test'})
+    assert(m2{p 'test'})
+    assert(!m1())
+    assert(!m2())
+  end
+
+  def m3(var, &block)
+    m(yield(var), &block)
+  end
+
+  def m4(&block)
+    m(m1(), &block)
+  end
+
+  def test_block_passing
+    assert(!m4())
+    assert(!m4 {})
+    assert_equal(100, m3(10) {|x|x*x})
+  end
+
+  class C
+    include Enumerable
+    def initialize
+      @a = [1,2,3]
     end
+    def each(&block)
+      @a.each(&block)
+    end
   end
-end
 
-A::B.c
-A::B.remove_const :C
-p A::B.c
+  def test_collect
+    assert_equal([1,2,3], C.new.collect{|n| n})
+  end
 
-__END__
+  def test_proc
+    assert_instance_of(Proc, lambda{})
+    assert_instance_of(Proc, Proc.new{})
+    lambda{|a|assert_equal(a, 1)}.call(1)
+  end
 
-Const = :top
-class A
-  Const = :A
-end
+  def test_block
+    assert_instance_of(NilClass, get_block)
+    assert_instance_of(Proc, get_block{})
+  end
 
-class C
-  Const = :C
-  def m
-    p A.class_eval('Const')
+  def test_argument
+    assert_nothing_raised {lambda{||}.call}
+    assert_raises(ArgumentError) {lambda{||}.call(1)}
+    assert_nothing_raised {lambda{|a,|}.call(1)}
+    assert_raises(ArgumentError) {lambda{|a,|}.call()}
+    assert_raises(ArgumentError) {lambda{|a,|}.call(1,2)}
   end
-end
 
-C.new.m
+  def get_block(&block)
+    block
+  end
 
-__END__
+  def test_get_block
+    assert_instance_of(Proc, get_block{})
+    assert_nothing_raised {get_block{||}.call()}
+    assert_nothing_raised {get_block{||}.call(1)}
+    assert_nothing_raised {get_block{|a,|}.call(1)}
+    assert_nothing_raised {get_block{|a,|}.call()}
+    assert_nothing_raised {get_block{|a,|}.call(1,2)}
 
-p 1.times{
-  break :boo
-}
+    assert_nothing_raised {get_block(&lambda{||}).call()}
+    assert_raises(ArgumentError) {get_block(&lambda{||}).call(1)}
+    assert_nothing_raised {get_block(&lambda{|a,|}).call(1)}
+    assert_raises(ArgumentError) {get_block(&lambda{|a,|}).call(1,2)}
 
-__END__
+    block = get_block{11}
+    assert_instance_of(Proc, block)
+    assert_instance_of(Proc, block.to_proc)
+    assert_equal(block.clone.call, 11)
+    assert_instance_of(Proc, get_block(&block))
 
-class Range
-  def each
-    i = first
-    while i<last
-      yield(i)
-      i = i.succ
+    lmd = lambda{44}
+    assert_instance_of(Proc, lmd)
+    assert_instance_of(Proc, lmd.to_proc)
+    assert_equal(lmd.clone.call, 44)
+    assert_instance_of(Proc, get_block(&lmd))
+
+    assert_equal(1, Proc.new{|a,| a}.call(1,2,3))
+    assert_nothing_raised {Proc.new{|a,|}.call(1,2)}
+  end
+
+  def return1_test
+    Proc.new {
+      return 55
+    }.call + 5
+  end
+
+  def test_return1
+    assert_equal(55, return1_test())
+  end
+
+  def return2_test
+    lambda {
+      return 55
+    }.call + 5
+  end
+
+  def test_return2
+    assert_equal(60, return2_test())
+  end
+
+  def proc_call(&b)
+    b.call
+  end
+  def proc_yield()
+    yield
+  end
+  def proc_return1
+    proc_call{return 42}+1
+  end
+
+  def test_proc_return1
+    assert_equal(42, proc_return1())
+  end
+
+  def proc_return2
+    proc_yield{return 42}+1
+  end
+
+  def test_proc_return2
+    assert_equal(42, proc_return2())
+  end
+
+  def test_ljump
+    assert_raises(LocalJumpError) {get_block{break}.call}
+
+    # cannot use assert_nothing_raised due to passing block.
+    begin
+      val = lambda{break 11}.call
+    rescue LocalJumpError
+      assert(false, "LocalJumpError occurred from break in lambda")
+    else
+      assert(11, val)
     end
+
+    block = get_block{11}
+    lmd = lambda{44}
+    assert_equal(0, block.arity)
+    assert_equal(0, lmd.arity)
+    assert_equal(0, lambda{||}.arity)
+    assert_equal(1, lambda{|a|}.arity)
+    assert_equal(1, lambda{|a,|}.arity)
+    assert_equal(2, lambda{|a,b|}.arity)
   end
-end
 
-module Enumerable
-  def map
-    each{|e|
-      yield(e)
+  def marity_test(m)
+    mobj = method(m)
+    assert_equal(mobj.arity, mobj.to_proc.arity)
+  end
+
+  def test_marity
+    marity_test(:assert)
+    marity_test(:marity_test)
+    marity_test(:p)
+
+    lambda(&method(:assert)).call(true)
+    lambda(&get_block{|a,n| assert(a,n)}).call(true, "marity")
+  end
+
+  def foo
+    yield([:key, :value])
+  end
+  def bar(&blk)
+    blk.call([:key, :value])
+  end
+
+  def test_yield_vs_call
+    foo{|k,v| assert_equal([:key, :value], [k,v])}
+    bar{|k,v| assert_equal([:key, :value], [k,v])}
+  end
+
+  class H
+    def each
+      yield [:key, :value]
+    end
+  end
+
+  def test_assoc_yield
+    [{:key=>:value}, H.new].each {|h|
+      h.each{|a| assert_equal([:key, :value], a)}
+      h.each{|*a| assert_equal([[:key, :value]], a)}
+      h.each{|k,v| assert_equal([:key, :value], [k,v])}
     }
   end
+
+  class ITER_TEST1
+    def a
+      block_given?
+    end
+  end
+
+  class ITER_TEST2 < ITER_TEST1
+    include Test::Unit::Assertions
+    def a
+      assert(super)
+      super
+    end
+  end
+
+  def test_iter_test2
+    assert(ITER_TEST2.new.a {})
+  end
+
+  class ITER_TEST3
+    def foo x
+      return yield if block_given?
+      x
+    end
+  end
+
+  class ITER_TEST4 < ITER_TEST3
+    include Test::Unit::Assertions
+    def foo x
+      assert_equal(super, yield)
+      assert_equal(x, super(x, &nil))
+    end
+  end
+
+  def test_iter4
+    ITER_TEST4.new.foo(44){55}
+  end
+
+  def test_break__nested_loop1
+    _test_break__nested_loop1 do
+      break
+    end
+  end
+
+  def _test_break__nested_loop1
+    while true
+      yield
+    end
+    assert(false, "must not reach here")
+  end
+
+  def test_break__nested_loop2
+    _test_break__nested_loop2 do
+      break
+    end
+  end
+
+  def _test_break__nested_loop2
+    until false
+      yield
+    end
+    assert(false, "must not reach here")
+  end
+
+  def test_break__nested_loop3
+    _test_break__nested_loop3 do
+      break
+    end
+  end
+
+  def _test_break__nested_loop3
+    loop do
+      yield
+    end
+    assert(false, "must not reach here")
+  end
+
+  def test_break_from_enum
+    result = ["a"].inject("ng") {|x,y| break "ok"}
+    assert_equal("ok", result)
+  end
+
+  def _test_return_trace_func(x)
+    set_trace_func(proc {})
+    [].fetch(2) {return x}
+  ensure
+    set_trace_func(nil)
+  end
+
+  def test_return_trace_func
+    ok = "returned gracefully"
+    result = "skipped"
+    result = _test_return_trace_func(ok)
+  ensure
+    assert_equal(ok, result)
+    return
+  end
 end
-
-p((1..3).map{|e|
-  break :ok
-  # break I
-})
-__END__
-["a"].inject("ng"){|x,y|
-  break "ok"
-}

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/vm.c	2005-12-28 06:38:36 UTC (rev 334)
@@ -700,36 +700,29 @@
                         yarv_control_frame_t *cfp,
                         char *file, int line_no, VALUE ary)
 {
-  VALUE str = 0;
-  char buf[BUFSIZE];
-
-  if(cfp->iseq != 0){
-    if(cfp->pc != 0){
-      line_no = th_get_sourceline(cfp);
-      snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
-               file = RSTRING(cfp->iseq->file_name)->ptr,
-               line_no, RSTRING(cfp->iseq->name)->ptr);
+  VALUE str;
+  
+  while(cfp != limit_cfp){
+    str = 0;
+    if(cfp->iseq != 0){
+      if(cfp->pc != 0){
+        yarv_iseq_t *iseq = cfp->iseq;
+        line_no = th_get_sourceline(cfp);
+        file = RSTRING(iseq->file_name)->ptr;
+        str = rb_sprintf("%s:%d:in `%s'",
+                         file, line_no, RSTRING(iseq->name)->ptr);
+        rb_ary_push(ary, str);
+      }
+      else{
+        struct yarv_cmethod_info *cmi = (void *)cfp->iseq;
+        str = rb_sprintf("%s:%d:in `%s'",
+                         file, line_no, rb_id2name(cmi->id));
+        rb_ary_push(ary, str);
+      }
     }
-    else{
-      struct yarv_cmethod_info *cmi = (void *)cfp->iseq;
-      snprintf(buf, BUFSIZE, "%s:%d:in `%s'",
-               file, line_no, rb_id2name(cmi->id));
-    }
-    str = rb_str_new2(buf);
+    cfp = YARV_NEXT_CONTROL_FRAME(cfp);
   }
-  else if(0 && cfp->magic == FRAME_MAGIC_IFUNC){
-    snprintf(buf, BUFSIZE, "::in `<ifunc>'"); /*, ""%s:%d:in `<ifunc>'",
-        file, line_no);*/
-    str = rb_str_new2(buf);
-  }
-  
-  if(limit_cfp != cfp){
-    th_backtrace_each(th, limit_cfp, cfp-1, file, line_no, ary);
-  }
-  if(str){
-    rb_ary_push(ary, str);
-  }
-  return str;
+  return rb_ary_reverse(ary);
 }
 
 VALUE
@@ -754,7 +747,7 @@
     ary = rb_ary_new();
   }
   
-  th_backtrace_each(th, cfp, top_of_cfp, "", 0, ary);
+  ary = th_backtrace_each(th, YARV_NEXT_CONTROL_FRAME(cfp), top_of_cfp, "", 0, ary);
   return ary;
 }
 

Modified: trunk/vm_macro.def
===================================================================
--- trunk/vm_macro.def	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/vm_macro.def	2005-12-28 06:38:36 UTC (rev 334)
@@ -32,21 +32,18 @@
   /* expand top of stack? */
   if(flag & VM_CALL_ARGS_SPLAT_BIT){
     VALUE ary = TOPN(0);
-    if(SPECIAL_CONST_P(ary) || BUILTIN_TYPE(ary) != T_ARRAY){
-      /* not a BUG */
-      /* TODO: check specification */
+    VALUE *ptr, *dst;
+    int i;
+    if (TYPE(ary) != T_ARRAY){
+      ary = rb_Array(ary);
     }
-    else{
-      VALUE *ptr = RARRAY(ary)->ptr;
-      VALUE *dst = GET_SP() - 1;
-      int i;
-
-      for(i=0; i<RARRAY(ary)->len; i++){
-        dst[i] = ptr[i];
-      }
-      num += i-1;
-      INC_SP(i-1);
+    ptr = RARRAY(ary)->ptr;
+    dst = GET_SP() - 1;
+    for(i=0; i<RARRAY(ary)->len; i++){
+      dst[i] = ptr[i];
     }
+    num += i-1;
+    INC_SP(i-1);
   }
 }
 
@@ -177,7 +174,7 @@
     }
   }
   /* stack overflow check */
-  if(CHECK_STACK_OVERFLOW(th, GET_CFP(), niseq->stack_max)){
+  if(CHECK_STACK_OVERFLOW(th, GET_CFP(), niseq->stack_max + 0x100)){
     rb_bug("stack overflow");
   }
   

Modified: trunk/yarvtest/test_flow.rb
===================================================================
--- trunk/yarvtest/test_flow.rb	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/yarvtest/test_flow.rb	2005-12-28 06:38:36 UTC (rev 334)
@@ -152,6 +152,29 @@
     }
   end
 
+  def test_break_from_ifunc
+    ae %q{
+      ["a"].inject("ng"){|x,y|
+        break :ok
+      }
+    }
+    ae %q{
+      ('a').map{|e|
+        break :ok
+      }
+    }
+    ae_flow %q{
+      ["a"].inject("ng"){|x,y|
+        break :ok
+      }
+    }
+    ae_flow %q{
+      ('a').map{|e|
+        break :ok
+      }
+    }
+  end
+  
   def test_break_ensure_interaction1
     # make sure that any 'break state' set up in the VM is c
     # the time of the ensure

Modified: trunk/yarvtest/test_method.rb
===================================================================
--- trunk/yarvtest/test_method.rb	2005-12-28 01:55:06 UTC (rev 333)
+++ trunk/yarvtest/test_method.rb	2005-12-28 06:38:36 UTC (rev 334)
@@ -52,8 +52,12 @@
       def m a
         a
       end
-      m(*1)
-    } if false # ruby HEAD cause TypeError
+      begin
+        m(*1)
+      rescue TypeError
+        :ok
+      end
+    }
     ae %q{
       def m a, b
         [a, b]


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

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