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