diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-12-31 15:02:22 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-12-31 15:02:22 +0000 |
commit | a3e1b1ce7ed7e7ffac23015fc2fde56511b30681 (patch) | |
tree | 7b725552a9a4ded93849ca2faab1b257f7761790 | |
parent | 3e7566d8fb5138bb9cd647e5fdefc54fc9803509 (diff) |
* Merge YARV
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11439 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
233 files changed, 45992 insertions, 13641 deletions
@@ -1,3 +1,7 @@ +Mon Jan 01 00:00:00 2007 Koichi Sasada <ko1@atdot.net> + + * Merge YARV + Sun Dec 31 16:22:48 2006 Eric Hodel <drbrain@segment7.net> * array.c: Fix Array#reject. @@ -44,7 +44,7 @@ static void ary_iter_check(VALUE ary) { if (FL_TEST(ary, ARY_ITERLOCK)) { - rb_raise(rb_eRuntimeError, "can't modify array during iteration"); + rb_raise(rb_eRuntimeError, "can't modify array during iteration"); } } #define ARY_SORTLOCK FL_USER3 @@ -143,7 +143,7 @@ ary_new(VALUE klass, long len) rb_raise(rb_eArgError, "array size too big"); } ary = ary_alloc(klass); - if (len == 0) len++; + if (len == 0) len++; RARRAY(ary)->ptr = ALLOC_N(VALUE, len); RARRAY(ary)->aux.capa = len; @@ -250,8 +250,6 @@ rb_check_array_type(VALUE ary) return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary"); } -static VALUE rb_ary_replace(VALUE, VALUE); - /* * call-seq: * Array.new(size=0, obj=nil) @@ -325,7 +323,7 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary) rb_raise(rb_eArgError, "array size too big"); } rb_ary_modify(ary); - RESIZE_CAPA(ary, len); + RESIZE_CAPA(ary, len); if (rb_block_given_p()) { long i; @@ -543,10 +541,10 @@ rb_ary_shift(VALUE ary) top = RARRAY_PTR(ary)[0]; if (!ARY_SHARED_P(ary)) { if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) { - MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1); + MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1); RARRAY(ary)->len--; - return top; - } + return top; + } RARRAY_PTR(ary)[0] = Qnil; ary_make_shared(ary); } @@ -590,7 +588,7 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) if (ARY_SHARED_P(ary)) { RARRAY(ary)->ptr += n; RARRAY(ary)->len -= n; - } + } else { MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n); RARRAY(ary)->len -= n; @@ -675,7 +673,7 @@ rb_ary_subseq(VALUE ary, long beg, long len) if (len == 0) return ary_new(klass, 0); shared = ary_make_shared(ary); - ptr = RARRAY_PTR(ary); + ptr = RARRAY_PTR(ary); ary2 = ary_alloc(klass); RARRAY(ary2)->ptr = ptr + beg; RARRAY(ary2)->len = len; @@ -775,8 +773,8 @@ rb_ary_at(VALUE ary, VALUE pos) /* * call-seq: * array.first -> obj or nil - * array.first(n) -> an_array - * + * array.first(n) -> an_array + * * Returns the first element, or the first +n+ elements, of the array. * If the array is empty, the first form returns <code>nil</code>, and the * second form returns an empty array. @@ -931,7 +929,7 @@ rb_ary_rindex(int argc, VALUE *argv, VALUE ary) long i = RARRAY_LEN(ary); if (rb_scan_args(argc, argv, "01", &val) == 0) { - RETURN_ENUMERATOR(ary, 0, 0); + RETURN_ENUMERATOR(ary, 0, 0); while (i--) { if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) return LONG2NUM(i); @@ -1145,11 +1143,23 @@ each_i(VALUE ary) * a -- b -- c -- */ +VALUE yarv_invoke_Array_each_special_block(VALUE ary); + VALUE rb_ary_each(VALUE ary) { + long i; + VALUE val; + RETURN_ENUMERATOR(ary, 0, 0); + + val = yarv_invoke_Array_each_special_block(ary); + if(val != Qundef){ + return val; + } + ITERATE(each_i, ary); + return ary; } static VALUE @@ -1158,7 +1168,7 @@ each_index_i(VALUE ary) long i; for (i=0; i<RARRAY_LEN(ary); i++) { - rb_yield(LONG2NUM(i)); + rb_yield(LONG2NUM(i)); } return ary; } @@ -1530,7 +1540,7 @@ sort_i(VALUE ary) data.ary = ary; data.ptr = RARRAY_PTR(ary); data.len = RARRAY_LEN(ary); ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2, &data); + rb_block_given_p()?sort_1:sort_2, &data); return ary; } @@ -1890,7 +1900,6 @@ rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary) return rb_ary_delete_at(ary, NUM2LONG(arg1)); } - static VALUE reject_bang_i(VALUE ary) { @@ -1905,10 +1914,10 @@ reject_bang_i(VALUE ary) } i2++; } + if (RARRAY_LEN(ary) == i2) return Qnil; if (i2 < RARRAY_LEN(ary)) RARRAY(ary)->len = i2; - return ary; } @@ -2075,7 +2084,7 @@ rb_ary_transpose(VALUE ary) * a #=> ["x", "y", "z"] */ -static VALUE +VALUE rb_ary_replace(VALUE copy, VALUE orig) { VALUE shared; @@ -2087,7 +2096,7 @@ rb_ary_replace(VALUE copy, VALUE orig) if (copy == orig) return copy; shared = ary_make_shared(orig); ptr = RARRAY(copy)->ptr; - xfree(ptr); + xfree(ptr); RARRAY(copy)->ptr = RARRAY(shared)->ptr; RARRAY(copy)->len = RARRAY(shared)->len; RARRAY(copy)->aux.shared = shared; @@ -2804,16 +2813,16 @@ flatten(VALUE ary, long idx, VALUE ary2, VALUE memo, int level) rb_ary_push(memo, id); rb_ary_splice(ary, idx, 1, ary2); if (level != 0) { - while (i < lim) { - VALUE tmp; + while (i < lim) { + VALUE tmp; - tmp = rb_check_array_type(rb_ary_elt(ary, i)); - if (!NIL_P(tmp)) { + tmp = rb_check_array_type(rb_ary_elt(ary, i)); + if (!NIL_P(tmp)) { n = flatten(ary, i, tmp, memo, level); - i += n; lim += n; - } - i++; + i += n; lim += n; } + i++; + } } rb_ary_pop(memo); @@ -2822,7 +2831,7 @@ flatten(VALUE ary, long idx, VALUE ary2, VALUE memo, int level) /* * call-seq: - * array.flatten! -> array or nil + * array.flatten! -> array or nil * array.flatten!(level) -> array or nil * * Flattens _self_ in place. @@ -2831,9 +2840,9 @@ flatten(VALUE ary, long idx, VALUE ary2, VALUE memo, int level) * argument determins the level of recursion to flatten. * * a = [ 1, 2, [3, [4, 5] ] ] - * a.flatten! #=> [1, 2, 3, 4, 5] - * a.flatten! #=> nil - * a #=> [1, 2, 3, 4, 5] + * a.flatten! #=> [1, 2, 3, 4, 5] + * a.flatten! #=> nil + * a #=> [1, 2, 3, 4, 5] * a = [ 1, 2, [3, [4, 5] ] ] * a.flatten!(1) #=> [1, 2, 3, [4, 5]] */ diff --git a/benchmark/bm_app_answer.rb b/benchmark/bm_app_answer.rb new file mode 100644 index 0000000..00f830e --- /dev/null +++ b/benchmark/bm_app_answer.rb @@ -0,0 +1,15 @@ +def ack(m, n)
+ if m == 0 then
+ n + 1
+ elsif n == 0 then
+ ack(m - 1, 1)
+ else
+ ack(m - 1, ack(m, n - 1))
+ end
+end
+
+def the_answer_to_life_the_universe_and_everything
+ (ack(3,7).to_s.split(//).inject(0){|s,x| s+x.to_i}.to_s + "2" ).to_i
+end
+
+answer = the_answer_to_life_the_universe_and_everything
diff --git a/benchmark/bm_app_factorial.rb b/benchmark/bm_app_factorial.rb new file mode 100644 index 0000000..cfafd62 --- /dev/null +++ b/benchmark/bm_app_factorial.rb @@ -0,0 +1,11 @@ +def fact(n)
+ if(n > 1)
+ n * fact(n-1)
+ else
+ 1
+ end
+end
+
+8.times{
+ fact(5000)
+}
\ No newline at end of file diff --git a/benchmark/bm_app_fib.rb b/benchmark/bm_app_fib.rb new file mode 100644 index 0000000..65a149e --- /dev/null +++ b/benchmark/bm_app_fib.rb @@ -0,0 +1,10 @@ +def fib n
+ if n < 3
+ 1
+ else
+ fib(n-1) + fib(n-2)
+ end
+end
+
+fib(34)
+
diff --git a/benchmark/bm_app_mandelbrot.rb b/benchmark/bm_app_mandelbrot.rb new file mode 100644 index 0000000..e981775 --- /dev/null +++ b/benchmark/bm_app_mandelbrot.rb @@ -0,0 +1,23 @@ +require 'complex'
+
+def mandelbrot? z
+ i = 0
+ while i<100
+ i+=1
+ z = z * z
+ return false if z.abs > 2
+ end
+ true
+end
+
+ary = []
+
+(0..100).each{|dx|
+ (0..100).each{|dy|
+ x = dx / 50.0
+ y = dy / 50.0
+ c = Complex(x, y)
+ ary << c if mandelbrot?(c)
+ }
+}
+
diff --git a/benchmark/bm_app_pentomino.rb b/benchmark/bm_app_pentomino.rb new file mode 100644 index 0000000..0fc80fa --- /dev/null +++ b/benchmark/bm_app_pentomino.rb @@ -0,0 +1,259 @@ +#!/usr/local/bin/ruby
+# This program is contributed by Shin Nishiyama
+
+
+# modified by K.Sasada
+
+NP = 5
+ROW = 8 + NP
+COL = 8
+
+$p = []
+$b = []
+$no = 0
+
+def piece(n, a, nb)
+ nb.each{|x|
+ a[n] = x
+ if n == NP-1
+ $p << [a.sort]
+ else
+ nbc=nb.clone
+ [-ROW, -1, 1, ROW].each{|d|
+ if x+d > 0 and not a.include?(x+d) and not nbc.include?(x+d)
+ nbc << x+d
+ end
+ }
+ nbc.delete x
+ piece(n+1,a[0..n],nbc)
+ end
+ }
+end
+
+def kikaku(a)
+ a.collect {|x| x - a[0]}
+end
+def ud(a)
+ kikaku(a.collect {|x| ((x+NP)%ROW)-ROW*((x+NP)/ROW) }.sort)
+end
+def rl(a)
+ kikaku(a.collect {|x| ROW*((x+NP)/ROW)+ROW-((x+NP)%ROW)}.sort)
+end
+def xy(a)
+ kikaku(a.collect {|x| ROW*((x+NP)%ROW) + (x+NP)/ROW }.sort)
+end
+
+def mkpieces
+ piece(0,[],[0])
+ $p.each do |a|
+ a0 = a[0]
+ a[1] = ud(a0)
+ a[2] = rl(a0)
+ a[3] = ud(rl(a0))
+ a[4] = xy(a0)
+ a[5] = ud(xy(a0))
+ a[6] = rl(xy(a0))
+ a[7] = ud(rl(xy(a0)))
+ a.sort!
+ a.uniq!
+ end
+ $p.uniq!.sort! {|x,y| x[0] <=> y[0] }
+end
+
+def mkboard
+ (0...ROW*COL).each{|i|
+ if i % ROW >= ROW-NP
+ $b[i] = -2
+ else
+ $b[i] = -1
+ end
+ $b[3*ROW+3]=$b[3*ROW+4]=$b[4*ROW+3]=$b[4*ROW+4]=-2
+ }
+end
+
+def pboard
+ return # skip print
+ print "No. #$no\n"
+ (0...COL).each{|i|
+ print "|"
+ (0...ROW-NP).each{|j|
+ x = $b[i*ROW+j]
+ if x < 0
+ print "..|"
+ else
+ printf "%2d|",x+1
+ end
+ }
+ print "\n"
+ }
+ print "\n"
+end
+
+$pnum=[]
+def setpiece(a,pos)
+ if a.length == $p.length then
+ $no += 1
+ pboard
+ return
+ end
+ while $b[pos] != -1
+ pos += 1
+ end
+ ($pnum - a).each do |i|
+ $p[i].each do |x|
+ f = 0
+ x.each{|s|
+ if $b[pos+s] != -1
+ f=1
+ break
+ end
+ }
+ if f == 0 then
+ x.each{|s|
+ $b[pos+s] = i
+ }
+ a << i
+ setpiece(a.clone, pos)
+ a.pop
+ x.each{|s|
+ $b[pos+s] = -1
+ }
+ end
+ end
+ end
+end
+
+mkpieces
+mkboard
+$p[4] = [$p[4][0]]
+$pnum = (0...$p.length).to_a
+setpiece([],0)
+
+
+__END__
+
+# original
+
+NP = 5
+ROW = 8 + NP
+COL = 8
+
+$p = []
+$b = []
+$no = 0
+
+def piece(n,a,nb)
+ for x in nb
+ a[n] = x
+ if n == NP-1
+ $p << [a.sort]
+ else
+ nbc=nb.clone
+ for d in [-ROW, -1, 1, ROW]
+ if x+d > 0 and not a.include?(x+d) and not nbc.include?(x+d)
+ nbc << x+d
+ end
+ end
+ nbc.delete x
+ piece(n+1,a[0..n],nbc)
+ end
+ end
+end
+
+def kikaku(a)
+ a.collect {|x| x - a[0]}
+end
+def ud(a)
+ kikaku(a.collect {|x| ((x+NP)%ROW)-ROW*((x+NP)/ROW) }.sort)
+end
+def rl(a)
+ kikaku(a.collect {|x| ROW*((x+NP)/ROW)+ROW-((x+NP)%ROW)}.sort)
+end
+def xy(a)
+ kikaku(a.collect {|x| ROW*((x+NP)%ROW) + (x+NP)/ROW }.sort)
+end
+
+def mkpieces
+ piece(0,[],[0])
+ $p.each do |a|
+ a0 = a[0]
+ a[1] = ud(a0)
+ a[2] = rl(a0)
+ a[3] = ud(rl(a0))
+ a[4] = xy(a0)
+ a[5] = ud(xy(a0))
+ a[6] = rl(xy(a0))
+ a[7] = ud(rl(xy(a0)))
+ a.sort!
+ a.uniq!
+ end
+ $p.uniq!.sort! {|x,y| x[0] <=> y[0] }
+end
+
+def mkboard
+ for i in 0...ROW*COL
+ if i % ROW >= ROW-NP
+ $b[i] = -2
+ else
+ $b[i] = -1
+ end
+ $b[3*ROW+3]=$b[3*ROW+4]=$b[4*ROW+3]=$b[4*ROW+4]=-2
+ end
+end
+
+def pboard
+ print "No. #$no\n"
+ for i in 0...COL
+ print "|"
+ for j in 0...ROW-NP
+ x = $b[i*ROW+j]
+ if x < 0
+ print "..|"
+ else
+ printf "%2d|",x+1
+ end
+ end
+ print "\n"
+ end
+ print "\n"
+end
+
+$pnum=[]
+def setpiece(a,pos)
+ if a.length == $p.length then
+ $no += 1
+ pboard
+ return
+ end
+ while $b[pos] != -1
+ pos += 1
+ end
+ ($pnum - a).each do |i|
+ $p[i].each do |x|
+ f = 0
+ for s in x do
+ if $b[pos+s] != -1
+ f=1
+ break
+ end
+ end
+ if f == 0 then
+ for s in x do
+ $b[pos+s] = i
+ end
+ a << i
+ setpiece(a.clone, pos)
+ a.pop
+ for s in x do
+ $b[pos+s] = -1
+ end
+ end
+ end
+ end
+end
+
+mkpieces
+mkboard
+$p[4] = [$p[4][0]]
+$pnum = (0...$p.length).to_a
+setpiece([],0)
diff --git a/benchmark/bm_app_raise.rb b/benchmark/bm_app_raise.rb new file mode 100644 index 0000000..0e3297e --- /dev/null +++ b/benchmark/bm_app_raise.rb @@ -0,0 +1,8 @@ +i=0
+while i<300000
+ i+=1
+ begin
+ raise
+ rescue
+ end
+end
diff --git a/benchmark/bm_app_strconcat.rb b/benchmark/bm_app_strconcat.rb new file mode 100644 index 0000000..cc0e929 --- /dev/null +++ b/benchmark/bm_app_strconcat.rb @@ -0,0 +1,5 @@ +i=0
+while i<500000
+ "#{1+1} #{1+1} #{1+1}"
+ i+=1
+end
diff --git a/benchmark/bm_app_tak.rb b/benchmark/bm_app_tak.rb new file mode 100644 index 0000000..d70d5db --- /dev/null +++ b/benchmark/bm_app_tak.rb @@ -0,0 +1,13 @@ +
+def tak x, y, z
+ unless y < x
+ z
+ else
+ tak( tak(x-1, y, z),
+ tak(y-1, z, x),
+ tak(z-1, x, y))
+ end
+end
+
+tak(18, 9, 0)
+
diff --git a/benchmark/bm_app_tarai.rb b/benchmark/bm_app_tarai.rb new file mode 100644 index 0000000..851f36d --- /dev/null +++ b/benchmark/bm_app_tarai.rb @@ -0,0 +1,10 @@ +def tarai( x, y, z )
+ if x <= y
+ then y
+ else tarai(tarai(x-1, y, z),
+ tarai(y-1, z, x),
+ tarai(z-1, x, y))
+ end
+end
+
+tarai(12, 6, 0)
diff --git a/benchmark/bm_loop_times.rb b/benchmark/bm_loop_times.rb new file mode 100644 index 0000000..6bda28d --- /dev/null +++ b/benchmark/bm_loop_times.rb @@ -0,0 +1 @@ +30000000.times{|e|}
diff --git a/benchmark/bm_loop_whileloop.rb b/benchmark/bm_loop_whileloop.rb new file mode 100644 index 0000000..59b89cc --- /dev/null +++ b/benchmark/bm_loop_whileloop.rb @@ -0,0 +1,4 @@ +i = 0
+while i<30000000 # benchmark loop 1
+ i+=1
+end
diff --git a/benchmark/bm_loop_whileloop2.rb b/benchmark/bm_loop_whileloop2.rb new file mode 100644 index 0000000..976d4a9 --- /dev/null +++ b/benchmark/bm_loop_whileloop2.rb @@ -0,0 +1,5 @@ +i=0
+while i<6000000 # benchmark loop 2
+ i+=1
+end
+
diff --git a/benchmark/bm_so_ackermann.rb b/benchmark/bm_so_ackermann.rb new file mode 100644 index 0000000..fce9585 --- /dev/null +++ b/benchmark/bm_so_ackermann.rb @@ -0,0 +1,19 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: ackermann-ruby.code,v 1.4 2004/11/13 07:40:41 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+
+def ack(m, n)
+ if m == 0 then
+ n + 1
+ elsif n == 0 then
+ ack(m - 1, 1)
+ else
+ ack(m - 1, ack(m, n - 1))
+ end
+end
+
+NUM = 9
+ack(3, NUM)
+
+
diff --git a/benchmark/bm_so_array.rb b/benchmark/bm_so_array.rb new file mode 100644 index 0000000..a82a37c --- /dev/null +++ b/benchmark/bm_so_array.rb @@ -0,0 +1,23 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: ary-ruby.code,v 1.4 2004/11/13 07:41:27 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+# with help from Paul Brannan and Mark Hubbart
+
+n = 9000 # Integer(ARGV.shift || 1)
+
+x = Array.new(n)
+y = Array.new(n, 0)
+
+n.times{|bi|
+ x[bi] = bi + 1
+}
+
+(0 .. 999).each do |e|
+ (n-1).step(0,-1) do |bi|
+ y[bi] += x.at(bi)
+ end
+end
+# puts "#{y.first} #{y.last}"
+
+
diff --git a/benchmark/bm_so_concatenate.rb b/benchmark/bm_so_concatenate.rb new file mode 100644 index 0000000..153efea --- /dev/null +++ b/benchmark/bm_so_concatenate.rb @@ -0,0 +1,18 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: strcat-ruby.code,v 1.4 2004/11/13 07:43:28 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+# based on code from Aristarkh A Zagorodnikov and Dat Nguyen
+
+STUFF = "hello\n"
+i=0
+while i<10
+ i+=1
+ hello = ''
+ 400000.times do |e|
+ hello << STUFF
+ end
+end
+# puts hello.length
+
+
diff --git a/benchmark/bm_so_count_words.rb b/benchmark/bm_so_count_words.rb new file mode 100644 index 0000000..a24062d --- /dev/null +++ b/benchmark/bm_so_count_words.rb @@ -0,0 +1,18 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: wc-ruby.code,v 1.4 2004/11/13 07:43:32 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+# with help from Paul Brannan
+
+input = open(File.join(File.dirname($0), 'wc.input'), 'rb')
+
+nl = nw = nc = 0
+while true
+ data = (input.read(4096) or break) << (input.gets || "")
+ nc += data.length
+ nl += data.count("\n")
+ ((data.strip! || data).tr!("\n", " ") || data).squeeze!
+ #nw += data.count(" ") + 1
+end
+# STDERR.puts "#{nl} #{nw} #{nc}"
+
diff --git a/benchmark/bm_so_exception.rb b/benchmark/bm_so_exception.rb new file mode 100644 index 0000000..d829474 --- /dev/null +++ b/benchmark/bm_so_exception.rb @@ -0,0 +1,61 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: except-ruby.code,v 1.4 2004/11/13 07:41:33 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+
+$HI = 0
+$LO = 0
+NUM = 250000 # Integer(ARGV[0] || 1)
+
+
+class Lo_Exception < Exception
+ def initialize(num)
+ @value = num
+ end
+end
+
+class Hi_Exception < Exception
+ def initialize(num)
+ @value = num
+ end
+end
+
+def some_function(num)
+ begin
+ hi_function(num)
+ rescue
+ print "We shouldn't get here, exception is: #{$!.type}\n"
+ end
+end
+
+def hi_function(num)
+ begin
+ lo_function(num)
+ rescue Hi_Exception
+ $HI = $HI + 1
+ end
+end
+
+def lo_function(num)
+ begin
+ blowup(num)
+ rescue Lo_Exception
+ $LO = $LO + 1
+ end
+end
+
+def blowup(num)
+ if num % 2 == 0
+ raise Lo_Exception.new(num)
+ else
+ raise Hi_Exception.new(num)
+ end
+end
+
+
+i = 1
+max = NUM+1
+while i < max
+ i+=1
+ some_function(i+1)
+end
diff --git a/benchmark/bm_so_lists.rb b/benchmark/bm_so_lists.rb new file mode 100644 index 0000000..1fcf24b --- /dev/null +++ b/benchmark/bm_so_lists.rb @@ -0,0 +1,47 @@ +#from http://www.bagley.org/~doug/shootout/bench/lists/lists.ruby
+
+NUM = 100
+SIZE = 10000
+
+def test_lists()
+ # create a list of integers (Li1) from 1 to SIZE
+ li1 = (1..SIZE).to_a
+ # copy the list to li2 (not by individual items)
+ li2 = li1.dup
+ # remove each individual item from left side of li2 and
+ # append to right side of li3 (preserving order)
+ li3 = Array.new
+ while (not li2.empty?)
+ li3.push(li2.shift)
+ end
+ # li2 must now be empty
+ # remove each individual item from right side of li3 and
+ # append to right side of li2 (reversing list)
+ while (not li3.empty?)
+ li2.push(li3.pop)
+ end
+ # li3 must now be empty
+ # reverse li1 in place
+ li1.reverse!
+ # check that first item is now SIZE
+ if li1[0] != SIZE then
+ p "not SIZE"
+ 0
+ else
+ # compare li1 and li2 for equality
+ if li1 != li2 then
+ return(0)
+ else
+ # return the length of the list
+ li1.length
+ end
+ end
+end
+
+i = 0
+while i<NUM
+ i+=1
+ result = test_lists()
+end
+
+result
diff --git a/benchmark/bm_so_matrix.rb b/benchmark/bm_so_matrix.rb new file mode 100644 index 0000000..2ba2220 --- /dev/null +++ b/benchmark/bm_so_matrix.rb @@ -0,0 +1,48 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: matrix-ruby.code,v 1.4 2004/11/13 07:42:14 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+
+n = 60 #Integer(ARGV.shift || 1)
+
+size = 30
+
+def mkmatrix(rows, cols)
+ count = 1
+ mx = Array.new(rows)
+ (0 .. (rows - 1)).each do |bi|
+ row = Array.new(cols, 0)
+ (0 .. (cols - 1)).each do |j|
+ row[j] = count
+ count += 1
+ end
+ mx[bi] = row
+ end
+ mx
+end
+
+def mmult(rows, cols, m1, m2)
+ m3 = Array.new(rows)
+ (0 .. (rows - 1)).each do |bi|
+ row = Array.new(cols, 0)
+ (0 .. (cols - 1)).each do |j|
+ val = 0
+ (0 .. (cols - 1)).each do |k|
+ val += m1.at(bi).at(k) * m2.at(k).at(j)
+ end
+ row[j] = val
+ end
+ m3[bi] = row
+ end
+ m3
+end
+
+m1 = mkmatrix(size, size)
+m2 = mkmatrix(size, size)
+mm = Array.new
+n.times do
+ mm = mmult(size, size, m1, m2)
+end
+# puts "#{mm[0][0]} #{mm[2][3]} #{mm[3][2]} #{mm[4][4]}"
+
+
diff --git a/benchmark/bm_so_nested_loop.rb b/benchmark/bm_so_nested_loop.rb new file mode 100644 index 0000000..4667d1b --- /dev/null +++ b/benchmark/bm_so_nested_loop.rb @@ -0,0 +1,24 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: nestedloop-ruby.code,v 1.4 2004/11/13 07:42:22 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+# from Avi Bryant
+
+n = 16 # Integer(ARGV.shift || 1)
+x = 0
+n.times do
+ n.times do
+ n.times do
+ n.times do
+ n.times do
+ n.times do
+ x += 1
+ end
+ end
+ end
+ end
+ end
+end
+# puts x
+
+
diff --git a/benchmark/bm_so_object.rb b/benchmark/bm_so_object.rb new file mode 100644 index 0000000..a900177 --- /dev/null +++ b/benchmark/bm_so_object.rb @@ -0,0 +1,56 @@ +#!/usr/bin/ruby
+# -*- mode: ruby -*-
+# $Id: objinst-ruby.code,v 1.4 2004/11/13 07:42:25 bfulgham Exp $
+# http://www.bagley.org/~doug/shootout/
+# with help from Aristarkh Zagorodnikov
+
+class Toggle
+ def initialize(start_state)
+ @bool = start_state
+ end
+
+ def value
+ @bool
+ end
+
+ def activate
+ @bool = !@bool
+ self
+ end
+end
+
+class NthToggle < Toggle
+ def initialize(start_state, max_counter)
+ super start_state
+ @count_max = max_counter
+ @counter = 0
+ end
+
+ def activate
+ @counter += 1
+ if @counter >= @count_max
+ @bool = !@bool
+ @counter = 0
+ end
+ self
+ end
+end
+
+n = 1500000 # (ARGV.shift || 1).to_i
+
+toggle = Toggle.new 1
+5.times do
+ toggle.activate.value ? 'true' : 'false'
+end
+n.times do
+ toggle = Toggle.new 1
+end
+
+ntoggle = NthToggle.new 1, 3
+8.times do
+ ntoggle.activate.value ? 'true' : 'false'
+end
+n.times do
+ ntoggle = NthToggle.new 1, 3
+end
+
diff --git a/benchmark/bm_so_random.rb b/benchmark/bm_so_random.rb new file mode 100644 index 0000000..8bc3084 --- /dev/null +++ b/benchmark/bm_so_random.rb @@ -0,0 +1,20 @@ +# from http://www.bagley.org/~doug/shootout/bench/random/random.ruby
+
+IM = 139968.0
+IA = 3877.0
+IC = 29573.0
+
+$last = 42.0
+
+def gen_random(max)
+ (max * ($last = ($last * IA + IC) % IM)) / IM
+end
+
+N = 1000000
+
+i=0
+while i<N
+ i+=1
+ gen_random(100.0)
+end
+# "%.9f" % gen_random(100.0)
diff --git a/benchmark/bm_so_sieve.rb b/benchmark/bm_so_sieve.rb new file mode 100644 index 0000000..c84d5bf --- /dev/null +++ b/benchmark/bm_so_sieve.rb @@ -0,0 +1,24 @@ +# from http://www.bagley.org/~doug/shootout/bench/sieve/sieve.ruby
+num = 40
+count = i = j = 0
+flags0 = Array.new(8192,1)
+k = 0
+while k < num
+ k+=1
+ count = 0
+ flags = flags0.dup
+ i = 2
+ while i<8192
+ i+=1
+ if flags[i]
+ # remove all multiples of prime: i
+ j = i*i
+ while j < 8192
+ j += i
+ flags[j] = nil
+ end
+ count += 1
+ end
+ end
+end
+count
diff --git a/benchmark/bm_vm1_block.rb b/benchmark/bm_vm1_block.rb new file mode 100644 index 0000000..1a7f98b --- /dev/null +++ b/benchmark/bm_vm1_block.rb @@ -0,0 +1,10 @@ +def m
+ yield
+end
+
+i=0
+while i<30000000 # while loop 1
+ i+=1
+ m{
+ }
+end
\ No newline at end of file diff --git a/benchmark/bm_vm1_const.rb b/benchmark/bm_vm1_const.rb new file mode 100644 index 0000000..0077592 --- /dev/null +++ b/benchmark/bm_vm1_const.rb @@ -0,0 +1,8 @@ +Const = 1
+
+i = 0
+while i<30000000 # while loop 1
+ i+= 1
+ j = Const
+ k = Const
+end
diff --git a/benchmark/bm_vm1_ensure.rb b/benchmark/bm_vm1_ensure.rb new file mode 100644 index 0000000..cdb4444 --- /dev/null +++ b/benchmark/bm_vm1_ensure.rb @@ -0,0 +1,11 @@ +i=0
+while i<30000000 # benchmark loop 1
+ i+=1
+ begin
+ begin
+ ensure
+ end
+ ensure
+ end
+end
+
diff --git a/benchmark/bm_vm1_length.rb b/benchmark/bm_vm1_length.rb new file mode 100644 index 0000000..764d77b --- /dev/null +++ b/benchmark/bm_vm1_length.rb @@ -0,0 +1,9 @@ +a = 'abc'
+b = [1, 2, 3]
+i=0
+while i<30000000 # while loop 1
+ i+=1
+ a.length
+ b.length
+end
+
diff --git a/benchmark/bm_vm1_rescue.rb b/benchmark/bm_vm1_rescue.rb new file mode 100644 index 0000000..2904e1a --- /dev/null +++ b/benchmark/bm_vm1_rescue.rb @@ -0,0 +1,7 @@ +i=0
+while i<30000000 # while loop 1
+ i+=1
+ begin
+ rescue
+ end
+end
diff --git a/benchmark/bm_vm1_simplereturn.rb b/benchmark/bm_vm1_simplereturn.rb new file mode 100644 index 0000000..c0a20ba --- /dev/null +++ b/benchmark/bm_vm1_simplereturn.rb @@ -0,0 +1,9 @@ +def m
+ return 1
+end
+i=0
+while i<30000000 # while loop 1
+ i+=1
+ m
+end
+
diff --git a/benchmark/bm_vm1_swap.rb b/benchmark/bm_vm1_swap.rb new file mode 100644 index 0000000..785c999 --- /dev/null +++ b/benchmark/bm_vm1_swap.rb @@ -0,0 +1,8 @@ +a = 1
+b = 2
+i=0
+while i<30000000 # while loop 1
+ i+=1
+ a, b = b, a
+end
+
diff --git a/benchmark/bm_vm2_array.rb b/benchmark/bm_vm2_array.rb new file mode 100644 index 0000000..d1a989c --- /dev/null +++ b/benchmark/bm_vm2_array.rb @@ -0,0 +1,5 @@ +i=0
+while i<6000000 # benchmark loop 2
+ i+=1
+ a = [1,2,3,4,5,6,7,8,9,10]
+end
diff --git a/benchmark/bm_vm2_method.rb b/benchmark/bm_vm2_method.rb new file mode 100644 index 0000000..4c9734f --- /dev/null +++ b/benchmark/bm_vm2_method.rb @@ -0,0 +1,9 @@ +def m
+ nil
+end
+
+i=0
+while i<6000000 # benchmark loop 2
+ i+=1
+ m; m; m; m; m; m; m; m;
+end
diff --git a/benchmark/bm_vm2_poly_method.rb b/benchmark/bm_vm2_poly_method.rb new file mode 100644 index 0000000..3341ce6 --- /dev/null +++ b/benchmark/bm_vm2_poly_method.rb @@ -0,0 +1,20 @@ +class C1
+ def m
+ 1
+ end
+end
+class C2
+ def m
+ 2
+ end
+end
+
+o1 = C1.new
+o2 = C2.new
+
+i=0
+while i<6000000 # benchmark loop 2
+ o = (i % 2 == 0) ? o1 : o2
+ o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
+ i+=1
+end
diff --git a/benchmark/bm_vm2_poly_method_ov.rb b/benchmark/bm_vm2_poly_method_ov.rb new file mode 100644 index 0000000..b5255f8 --- /dev/null +++ b/benchmark/bm_vm2_poly_method_ov.rb @@ -0,0 +1,20 @@ +class C1
+ def m
+ 1
+ end
+end
+class C2
+ def m
+ 2
+ end
+end
+
+o1 = C1.new
+o2 = C2.new
+
+i=0
+while i<6000000 # benchmark loop 2
+ o = (i % 2 == 0) ? o1 : o2
+# o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
+ i+=1
+end
diff --git a/benchmark/bm_vm2_proc.rb b/benchmark/bm_vm2_proc.rb new file mode 100644 index 0000000..d289238 --- /dev/null +++ b/benchmark/bm_vm2_proc.rb @@ -0,0 +1,14 @@ +def m &b
+ b
+end
+
+pr = m{
+ a = 1
+}
+
+i=0
+while i<6000000 # benchmark loop 2
+ i+=1
+ pr.call
+end
+
diff --git a/benchmark/bm_vm2_regexp.rb b/benchmark/bm_vm2_regexp.rb new file mode 100644 index 0000000..515cd0e --- /dev/null +++ b/benchmark/bm_vm2_regexp.rb @@ -0,0 +1,6 @@ +i=0
+str = 'xxxhogexxx'
+while i<6000000 # benchmark loop 2
+ /hoge/ =~ str
+ i+=1
+end
diff --git a/benchmark/bm_vm2_send.rb b/benchmark/bm_vm2_send.rb new file mode 100644 index 0000000..5b23a24 --- /dev/null +++ b/benchmark/bm_vm2_send.rb @@ -0,0 +1,12 @@ +class C
+ def m
+ end
+end
+
+o = C.new
+
+i=0
+while i<6000000 # benchmark loop 2
+ i+=1
+ o.__send__ :m
+end
diff --git a/benchmark/bm_vm2_super.rb b/benchmark/bm_vm2_super.rb new file mode 100644 index 0000000..7511f7b --- /dev/null +++ b/benchmark/bm_vm2_super.rb @@ -0,0 +1,20 @@ +
+class C
+ def m
+ 1
+ end
+end
+
+class CC < C
+ def m
+ super()
+ end
+end
+
+obj = CC.new
+
+i = 0
+while i<6000000 # benchmark loop 2
+ obj.m
+ i+=1
+end
diff --git a/benchmark/bm_vm2_unif1.rb b/benchmark/bm_vm2_unif1.rb new file mode 100644 index 0000000..4df6c9f --- /dev/null +++ b/benchmark/bm_vm2_unif1.rb @@ -0,0 +1,8 @@ +i = 0
+def m a, b
+end
+
+while i<6000000 # benchmark loop 2
+ i+=1
+ m 100, 200
+end
diff --git a/benchmark/bm_vm2_zsuper.rb b/benchmark/bm_vm2_zsuper.rb new file mode 100644 index 0000000..c829bb9 --- /dev/null +++ b/benchmark/bm_vm2_zsuper.rb @@ -0,0 +1,20 @@ +i = 0
+
+class C
+ def m a
+ 1
+ end
+end
+
+class CC < C
+ def m a
+ super
+ end
+end
+
+obj = CC.new
+
+while i<6000000 # benchmark loop 2
+ obj.m 10
+ i+=1
+end
diff --git a/benchmark/bm_vm3_thread_create_join.rb b/benchmark/bm_vm3_thread_create_join.rb new file mode 100644 index 0000000..a99451a --- /dev/null +++ b/benchmark/bm_vm3_thread_create_join.rb @@ -0,0 +1,6 @@ +i=0
+while i<1000 # benchmark loop 3
+ i+=1
+ Thread.new{
+ }.join
+end
diff --git a/benchmark/bmx_temp.rb b/benchmark/bmx_temp.rb new file mode 100644 index 0000000..dc45f5a --- /dev/null +++ b/benchmark/bmx_temp.rb @@ -0,0 +1,57 @@ +
+i=0
+while i<20000000
+ x = 1 # "foo"
+ i+=1
+end
+
+__END__
+
+class Range
+ def each
+ f = self.first
+ l = self.last
+ while f < l
+ yield
+ f = f.succ
+ end
+ end
+end
+
+(0..10000000).each{
+}
+
+__END__
+class Fixnum_
+ def times
+ i = 0
+ while i<self
+ yield(i)
+ i+=1
+ end
+ end
+end
+
+10000000.times{
+}
+__END__
+
+ths = (1..10).map{
+ Thread.new{
+ 1000000.times{
+ }
+ }
+}
+ths.each{|e|
+ e.join
+}
+
+__END__
+$pr = proc{}
+def m
+ $pr.call
+end
+
+1000000.times{|e|
+ m
+}
diff --git a/benchmark/other-lang/ack.pl b/benchmark/other-lang/ack.pl new file mode 100644 index 0000000..8933c33 --- /dev/null +++ b/benchmark/other-lang/ack.pl @@ -0,0 +1,11 @@ +use integer;
+
+sub Ack {
+ return $_[0] ? ($_[1] ? Ack($_[0]-1, Ack($_[0], $_[1]-1))
+ : Ack($_[0]-1, 1))
+ : $_[1]+1;
+}
+
+my $NUM = 9;
+$NUM = 1 if ($NUM < 1);
+my $ack = Ack(3, $NUM);
diff --git a/benchmark/other-lang/ack.py b/benchmark/other-lang/ack.py new file mode 100644 index 0000000..971796f --- /dev/null +++ b/benchmark/other-lang/ack.py @@ -0,0 +1,16 @@ +import sys
+sys.setrecursionlimit(5000000)
+
+def Ack(M, N):
+ if (not M):
+ return( N + 1 )
+ if (not N):
+ return( Ack(M-1, 1) )
+ return( Ack(M-1, Ack(M, N-1)) )
+
+def main():
+ NUM = 9
+ sys.setrecursionlimit(10000)
+ Ack(3, NUM)
+
+main()
diff --git a/benchmark/other-lang/ack.rb b/benchmark/other-lang/ack.rb new file mode 100644 index 0000000..7886183 --- /dev/null +++ b/benchmark/other-lang/ack.rb @@ -0,0 +1,12 @@ +def ack(m, n)
+ if m == 0 then
+ n + 1
+ elsif n == 0 then
+ ack(m - 1, 1)
+ else
+ ack(m - 1, ack(m, n - 1))
+ end
+end
+
+NUM = 9
+ack(3, NUM)
diff --git a/benchmark/other-lang/ack.scm b/benchmark/other-lang/ack.scm new file mode 100644 index 0000000..e9e1886 --- /dev/null +++ b/benchmark/other-lang/ack.scm @@ -0,0 +1,7 @@ +(define (ack m n)
+ (cond ((zero? m) (+ n 1))
+ ((zero? n) (ack (- m 1) 1))
+ (else (ack (- m 1) (ack m (- n 1))))))
+
+(ack 3 9)
+
diff --git a/benchmark/other-lang/eval.rb b/benchmark/other-lang/eval.rb new file mode 100644 index 0000000..e6ff94d --- /dev/null +++ b/benchmark/other-lang/eval.rb @@ -0,0 +1,66 @@ +
+Bench = %w(
+ loop
+ ack
+ fib
+ tak
+ fact
+)
+
+Lang = <<EOP.map{|l| l.strip}
+ ruby-cyg
+ ../../../test6/miniruby
+ perl
+ python
+ gosh
+EOP
+
+Bench.replace ['loop2']
+Lang.replace ['ruby-cyg']
+
+Ext = %w(
+ .rb
+ .rb
+ .pl
+ .py
+ .scm
+)
+
+p Bench
+p Lang
+
+require 'benchmark'
+
+def bench cmd
+ m = Benchmark.measure{
+ #p cmd
+ system(cmd)
+ }
+ [m.utime, m.real]
+end
+
+Result = []
+Bench.each{|b|
+ r = []
+ Lang.each_with_index{|l, idx|
+ cmd = "#{l} #{b}#{Ext[idx]}"
+ r << bench(cmd)
+ }
+ Result << r
+}
+
+require 'pp'
+# utime
+puts Lang.join("\t")
+Bench.each_with_index{|b, bi|
+ print b, "\t"
+ puts Result[bi].map{|e| e[0]}.join("\t")
+}
+
+# rtime
+puts Lang.join("\t")
+Bench.each_with_index{|b, bi|
+ print b, "\t"
+ puts Result[bi].map{|e| e[1]}.join("\t")
+}
+
diff --git a/benchmark/other-lang/fact.pl b/benchmark/other-lang/fact.pl new file mode 100644 index 0000000..2cef185 --- /dev/null +++ b/benchmark/other-lang/fact.pl @@ -0,0 +1,13 @@ +sub fact{
+ my $n = @_[0];
+ if($n < 2){
+ return 1;
+ }
+ else{
+ return $n * fact($n-1);
+ }
+}
+
+for($i=0; $i<10000; $i++){
+ &fact(100);
+}
diff --git a/benchmark/other-lang/fact.py b/benchmark/other-lang/fact.py new file mode 100644 index 0000000..460e405 --- /dev/null +++ b/benchmark/other-lang/fact.py @@ -0,0 +1,18 @@ +#import sys
+#sys.setrecursionlimit(1000)
+
+def factL(n):
+ r = 1
+ for x in range(2, n):
+ r *= x
+ return r
+
+def factR(n):
+ if n < 2:
+ return 1
+ else:
+ return n * factR(n-1)
+
+for i in range(10000):
+ factR(100)
+
diff --git a/benchmark/other-lang/fact.rb b/benchmark/other-lang/fact.rb new file mode 100644 index 0000000..c753208 --- /dev/null +++ b/benchmark/other-lang/fact.rb @@ -0,0 +1,13 @@ +def fact(n)
+ if n < 2
+ 1
+ else
+ n * fact(n-1)
+ end
+end
+
+i=0
+while i<10000
+ i+=1
+ fact(100)
+end
diff --git a/benchmark/other-lang/fact.scm b/benchmark/other-lang/fact.scm new file mode 100644 index 0000000..511990f --- /dev/null +++ b/benchmark/other-lang/fact.scm @@ -0,0 +1,8 @@ +(define (fact n)
+ (if (< n 2)
+ 1
+ (* n (fact (- n 1)))))
+
+(dotimes (i 10000)
+ (fact 100))
+
diff --git a/benchmark/other-lang/fib.pl b/benchmark/other-lang/fib.pl new file mode 100644 index 0000000..d660a23 --- /dev/null +++ b/benchmark/other-lang/fib.pl @@ -0,0 +1,11 @@ +sub fib{
+ my $n = $_[0];
+ if($n < 3){
+ return 1;
+ }
+ else{
+ return fib($n-1) + fib($n-2);
+ }
+};
+
+&fib(34);
diff --git a/benchmark/other-lang/fib.py b/benchmark/other-lang/fib.py new file mode 100644 index 0000000..40f87f3 --- /dev/null +++ b/benchmark/other-lang/fib.py @@ -0,0 +1,7 @@ +def fib(n):
+ if n < 3:
+ return 1
+ else:
+ return fib(n-1) + fib(n-2)
+
+fib(34)
diff --git a/benchmark/other-lang/fib.rb b/benchmark/other-lang/fib.rb new file mode 100644 index 0000000..7e0e8da --- /dev/null +++ b/benchmark/other-lang/fib.rb @@ -0,0 +1,9 @@ +def fib n
+ if n < 3
+ 1
+ else
+ fib(n-1) + fib(n-2)
+ end
+end
+
+fib(34)
diff --git a/benchmark/other-lang/fib.scm b/benchmark/other-lang/fib.scm new file mode 100644 index 0000000..ea63503 --- /dev/null +++ b/benchmark/other-lang/fib.scm @@ -0,0 +1,7 @@ +(define (fib n)
+ (if (< n 3)
+ 1
+ (+ (fib (- n 1)) (fib (- n 2)))))
+
+(fib 34)
+
diff --git a/benchmark/other-lang/loop.pl b/benchmark/other-lang/loop.pl new file mode 100644 index 0000000..ecacef4 --- /dev/null +++ b/benchmark/other-lang/loop.pl @@ -0,0 +1,3 @@ +for($i=0; $i<30000000; $i++){
+}
+
diff --git a/benchmark/other-lang/loop.py b/benchmark/other-lang/loop.py new file mode 100644 index 0000000..b47089f --- /dev/null +++ b/benchmark/other-lang/loop.py @@ -0,0 +1,2 @@ +for i in xrange(30000000):
+ pass
diff --git a/benchmark/other-lang/loop.rb b/benchmark/other-lang/loop.rb new file mode 100644 index 0000000..35cd67a --- /dev/null +++ b/benchmark/other-lang/loop.rb @@ -0,0 +1,4 @@ +i=0
+while i<30000000
+ i+=1
+end
diff --git a/benchmark/other-lang/loop.scm b/benchmark/other-lang/loop.scm new file mode 100644 index 0000000..1646ac3 --- /dev/null +++ b/benchmark/other-lang/loop.scm @@ -0,0 +1 @@ +(dotimes (x 30000000))
diff --git a/benchmark/other-lang/loop2.rb b/benchmark/other-lang/loop2.rb new file mode 100644 index 0000000..f308592 --- /dev/null +++ b/benchmark/other-lang/loop2.rb @@ -0,0 +1 @@ +30000000.times{}
diff --git a/benchmark/other-lang/tak.pl b/benchmark/other-lang/tak.pl new file mode 100644 index 0000000..c7bb626 --- /dev/null +++ b/benchmark/other-lang/tak.pl @@ -0,0 +1,11 @@ +sub tak {
+ local($x, $y, $z) = @_;
+ if (!($y < $x)) {
+ return $z;
+ } else {
+ return &tak(&tak($x - 1, $y, $z),
+ &tak($y - 1, $z, $x),
+ &tak($z - 1, $x, $y));
+ }
+}
+&tak(18, 9, 0);
diff --git a/benchmark/other-lang/tak.py b/benchmark/other-lang/tak.py new file mode 100644 index 0000000..9b7bd8f --- /dev/null +++ b/benchmark/other-lang/tak.py @@ -0,0 +1,8 @@ +def tak(x, y, z):
+ if not(y<x):
+ return z
+ else:
+ return tak(tak(x-1, y, z),
+ tak(y-1, z, x),
+ tak(z-1, x, y))
+tak(18, 9, 0)
diff --git a/benchmark/other-lang/tak.rb b/benchmark/other-lang/tak.rb new file mode 100644 index 0000000..d70d5db --- /dev/null +++ b/benchmark/other-lang/tak.rb @@ -0,0 +1,13 @@ +
+def tak x, y, z
+ unless y < x
+ z
+ else
+ tak( tak(x-1, y, z),
+ tak(y-1, z, x),
+ tak(z-1, x, y))
+ end
+end
+
+tak(18, 9, 0)
+
diff --git a/benchmark/other-lang/tak.scm b/benchmark/other-lang/tak.scm new file mode 100644 index 0000000..45cc576 --- /dev/null +++ b/benchmark/other-lang/tak.scm @@ -0,0 +1,10 @@ +(define (tak x y z)
+ (if (not (< y x))
+ z
+ (tak (tak (- x 1) y z)
+ (tak (- y 1) z x)
+ (tak (- z 1) x y))))
+
+(tak 18 9 0)
+
+
diff --git a/benchmark/report.rb b/benchmark/report.rb new file mode 100644 index 0000000..99def55 --- /dev/null +++ b/benchmark/report.rb @@ -0,0 +1,81 @@ +#
+# YARV benchmark driver
+#
+
+require 'yarvutil'
+require 'benchmark'
+require 'rbconfig'
+
+def exec_command type, file, w
+ <<-EOP
+ $DRIVER_PATH = '#{File.dirname($0)}'
+ $LOAD_PATH.replace $LOAD_PATH | #{$LOAD_PATH.inspect}
+ require 'benchmark'
+ require 'yarvutil'
+# print '#{type}'
+ begin
+ puts Benchmark.measure{
+ #{w}('#{file}')
+ }.utime
+ rescue Exception => exec_command_error_variable
+ puts "\t" + exec_command_error_variable.message
+ end
+ EOP
+end
+
+def benchmark cmd
+ rubybin = ENV['RUBY'] || File.join(
+ Config::CONFIG["bindir"],
+ Config::CONFIG["ruby_install_name"] + Config::CONFIG["EXEEXT"])
+
+ IO.popen(rubybin, 'r+'){|io|
+ io.write cmd
+ io.close_write
+ return io.gets
+ }
+end
+
+def ruby_exec file
+ prog = exec_command 'ruby', file, 'load'
+ benchmark prog
+end
+
+def yarv_exec file
+ prog = exec_command 'yarv', file, 'YARVUtil.load_bm'
+ benchmark prog
+end
+
+$wr = $wy = nil
+
+def measure bench
+ file = File.dirname($0) + "/bm_#{bench}.rb"
+ r = ruby_exec(file).to_f
+ y = yarv_exec(file).to_f
+ puts "#{bench}\t#{r}\t#{y}"
+end
+
+def measure2
+ r = ruby_exec.to_f
+ y = yarv_exec.to_f
+ puts r/y
+end
+
+if $0 == __FILE__
+ %w{
+ whileloop
+ whileloop2
+ times
+ const
+ method
+ poly_method
+ block
+ rescue
+ rescue2
+ }.each{|bench|
+ measure bench
+ }
+end
+
+
+
+
diff --git a/benchmark/run.rb b/benchmark/run.rb new file mode 100644 index 0000000..b84d093 --- /dev/null +++ b/benchmark/run.rb @@ -0,0 +1,137 @@ +#
+# YARV benchmark driver
+#
+
+require 'yarvutil'
+require 'benchmark'
+require 'rbconfig'
+
+$yarvonly = false
+$rubyonly = false
+
+$results = []
+
+puts "ruby #{RUBY_VERSION} #{RUBY_PLATFORM}(#{RUBY_RELEASE_DATE})"
+puts YARVCore::VERSION + " rev: #{YARVCore::REV} (#{YARVCore::DATE})"
+puts YARVCore::OPTS
+puts
+
+def bm file
+ prog = File.read(file).map{|e| e.rstrip}.join("\n")
+ return if prog.empty?
+
+ /[a-z]+_(.+)\.rb/ =~ file
+ bm_name = $1
+ puts '-----------------------------------------------------------' unless $yarvonly || $rubyonly
+ puts "#{bm_name}: "
+
+
+puts <<EOS unless $yarvonly || $rubyonly
+#{prog}
+--
+EOS
+ #iseq = YARVUtil.parse(File.read(file))
+ #vm = YARVCore::VM.new
+ begin
+ Benchmark.bm{|x|
+ # x.report("yarv"){ YARVUtil.load_bm(file) }
+ } unless $yarvonly || $rubyonly
+
+ result = [bm_name]
+ result << ruby_exec(file) unless $yarvonly
+ result << yarv_exec(file) unless $rubyonly
+ $results << result
+
+ # puts YARVUtil.parse(File.read(file), file, 1).disasm
+
+ # x.report("ruby"){ load(file, false) }
+ # x.report("yarv"){ vm.eval iseq }
+ rescue Exception => e
+ puts
+ puts "** benchmark failure: #{e}"
+ puts e.backtrace
+ end
+end
+
+def exec_command type, file, w
+ <<-EOP
+ $DRIVER_PATH = '#{File.dirname($0)}'
+ $LOAD_PATH.replace $LOAD_PATH | #{$LOAD_PATH.inspect}
+ require 'benchmark'
+ require 'yarvutil'
+ print '#{type}'
+ begin
+ puts Benchmark.measure{
+ #{w}('#{file}')
+ }
+ rescue Exception => exec_command_error_variable
+ puts "\t" + exec_command_error_variable.message
+ end
+ EOP
+end
+
+def benchmark prog
+ rubybin = ENV['RUBY'] || File.join(
+ Config::CONFIG["bindir"],
+ Config::CONFIG["ruby_install_name"] + Config::CONFIG["EXEEXT"])
+
+ #
+ tmpfile = Tempfile.new('yarvbench')
+ tmpfile.write(prog)
+ tmpfile.close
+
+ cmd = "#{rubybin} #{tmpfile.path}"
+ result = `#{cmd}`
+ puts result
+ tmpfile.close(true)
+ result
+end
+
+def ruby_exec file
+ prog = exec_command 'ruby', file, 'load'
+ benchmark prog
+end
+
+def yarv_exec file
+ prog = exec_command 'yarv', file, 'YARVUtil.load_bm'
+ benchmark prog
+end
+
+if $0 == __FILE__
+ ARGV.each{|arg|
+ if /\A(--yarv)|(-y)/ =~ arg
+ $yarvonly = true
+ elsif /\A(--ruby)|(-r)/ =~ arg
+ $rubyonly = true
+ end
+ }
+ ARGV.delete_if{|arg|
+ /\A-/ =~ arg
+ }
+
+ if ARGV.empty?
+ Dir.glob(File.dirname(__FILE__) + '/bm_*.rb').sort.each{|file|
+ bm file
+ }
+ else
+ ARGV.each{|file|
+ Dir.glob(File.join(File.dirname(__FILE__), file + '*')){|ef|
+ # file = "#{File.dirname(__FILE__)}/#{file}.rb"
+ bm ef
+ }
+ }
+ end
+
+ puts
+ puts "-- benchmark summary ---------------------------"
+ $results.each{|res|
+ print res.shift, "\t"
+ (res||[]).each{|result|
+ /([\d\.]+)/ =~ result
+ print $1 + "\t" if $1
+ }
+ puts
+ }
+end
+
+
diff --git a/benchmark/run_rite.rb b/benchmark/run_rite.rb new file mode 100644 index 0000000..3b437c8 --- /dev/null +++ b/benchmark/run_rite.rb @@ -0,0 +1,129 @@ +#
+# YARV benchmark driver
+#
+
+require 'benchmark'
+require 'rbconfig'
+
+$yarvonly = false
+$rubyonly = false
+
+$results = []
+
+# prepare 'wc.input'
+def prepare_wc_input
+ wcinput = File.join(File.dirname($0), 'wc.input')
+ wcbase = File.join(File.dirname($0), 'wc.input.base')
+ unless FileTest.exist?(wcinput)
+ data = File.read(wcbase)
+ 13.times{
+ data << data
+ }
+ open(wcinput, 'w'){|f| f.write data}
+ end
+end
+
+prepare_wc_input
+
+def bm file
+ prog = File.read(file).map{|e| e.rstrip}.join("\n")
+ return if prog.empty?
+
+ /[a-z]+_(.+)\.rb/ =~ file
+ bm_name = $1
+ puts '-----------------------------------------------------------' unless $yarvonly || $rubyonly
+ puts "#{bm_name}: "
+
+
+puts <<EOS unless $yarvonly || $rubyonly
+#{prog}
+--
+EOS
+ #iseq = YARVUtil.parse(File.read(file))
+ #vm = YARVCore::VM.new
+ begin
+ result = [bm_name]
+ result << ruby_exec(file) unless $yarvonly
+ result << yarv_exec(file) unless $rubyonly
+ $results << result
+
+ # puts YARVUtil.parse(File.read(file), file, 1).disasm
+
+ # x.report("ruby"){ load(file, false) }
+ # x.report("yarv"){ vm.eval iseq }
+ rescue Exception => e
+ puts
+ puts "** benchmark failure: #{e}"
+ puts e.backtrace
+ end
+end
+
+def benchmark file, bin
+ m = Benchmark.measure{
+ `#{bin} #{$opts} #{file}`
+ }
+ sec = '%.3f' % m.real
+ puts " #{sec}"
+ sec
+end
+
+def ruby_exec file
+ print 'ruby'
+ benchmark file, $ruby_program
+end
+
+def yarv_exec file
+ print 'yarv'
+ benchmark file, $yarv_program
+end
+
+if $0 == __FILE__
+ ARGV.each{|arg|
+ case arg
+ when /\A--yarv-program=(.+)/
+ $yarv_program = $1
+ when /\A--ruby-program=(.+)/
+ $ruby_program = $1
+ when /\A--opts=(.+)/
+ $opts = $1
+ when /\A(--yarv)|(-y)/
+ $yarvonly = true
+ when /\A(--ruby)|(-r)/
+ $rubyonly = true
+ end
+ }
+ ARGV.delete_if{|arg|
+ /\A-/ =~ arg
+ }
+
+ puts "Ruby:"
+ system("#{$ruby_program} -v")
+ puts
+ puts "YARV:"
+ system("#{$yarv_program} -v")
+
+ if ARGV.empty?
+ Dir.glob(File.dirname(__FILE__) + '/bm_*.rb').sort.each{|file|
+ bm file
+ }
+ else
+ ARGV.each{|file|
+ Dir.glob(File.join(File.dirname(__FILE__), file + '*')){|ef|
+ # file = "#{File.dirname(__FILE__)}/#{file}.rb"
+ bm ef
+ }
+ }
+ end
+
+ puts
+ puts "-- benchmark summary ---------------------------"
+ $results.each{|res|
+ print res.shift, "\t"
+ (res||[]).each{|result|
+ /([\d\.]+)/ =~ result
+ print $1 + "\t" if $1
+ }
+ puts
+ }
+end
+
diff --git a/benchmark/runc.rb b/benchmark/runc.rb new file mode 100644 index 0000000..20e06b2 --- /dev/null +++ b/benchmark/runc.rb @@ -0,0 +1,29 @@ +#
+#
+#
+
+require 'benchmark'
+require 'rbconfig'
+
+$rubybin = ENV['RUBY'] || File.join(
+ Config::CONFIG["bindir"],
+ Config::CONFIG["ruby_install_name"] + Config::CONFIG["EXEEXT"])
+
+def runfile file
+ puts file
+ file = File.join(File.dirname($0), 'contrib', file)
+ Benchmark.bm{|x|
+ x.report('ruby'){
+ system("#{$rubybin} #{file}")
+ }
+ x.report('yarv'){
+ system("#{$rubybin} -rite -I.. #{file}")
+ }
+ }
+end
+
+ARGV.each{|file|
+ runfile file
+}
+
+
diff --git a/benchmark/wc.input.base b/benchmark/wc.input.base new file mode 100644 index 0000000..88b5c69 --- /dev/null +++ b/benchmark/wc.input.base @@ -0,0 +1,25 @@ +Subject: Re: Who was Izchak Miller?
+From: "Jane D. Anonymous" <nobody@yale.edu>
+Date: 1996/04/28
+Message-Id: <4lv7bc$oh@news.ycc.yale.edu>
+References: <317C405E.5DFA@panix.com> <4lk6vl$gde@ns.oar.net>
+To: 75176.2330@compuserve.com
+Content-Type: text/plain; charset=us-ascii
+Organization: Yale University
+X-Url: news:4lk6vl$gde@ns.oar.net
+Mime-Version: 1.0
+Newsgroups: rec.games.roguelike.nethack
+X-Mailer: Mozilla 1.1N (Macintosh; I; 68K)
+
+Hello there, Izchak Miller was my father. When I was younger I spent
+many a night, hunched over the keyboard with a cup of tea, playing
+nethack with him and my brother. my dad was a philosopher with a strong
+weakness for fantasy/sci fi. I remember when he started to get involved
+with the Nethack team- my brother's Dungeons and Dragons monster book
+found a regular place beside my dad's desk. it's nice to see him living
+on in the game he loved so much :-).
+ Tamar Miller
+
+The following is a really long word of 5000 characters:
+
+wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
diff --git a/blockinlining.c b/blockinlining.c new file mode 100644 index 0000000..7a74f34 --- /dev/null +++ b/blockinlining.c @@ -0,0 +1,461 @@ +/********************************************************************** + + blockinlining.c - + + $Author$ + $Date$ + + Copyright (C) 2004-2006 Koichi Sasada + +**********************************************************************/ + +#include "ruby.h" +#include "node.h" +#include "yarvcore.h" + +VALUE yarv_new_iseqval(VALUE node, VALUE name, VALUE file, + VALUE parent, VALUE type, VALUE block_opt, VALUE opt); + +static VALUE +yarv_iseq_special_block(yarv_iseq_t *iseq, void *builder) +{ +#if OPT_BLOCKINLINING + VALUE parent = Qfalse; + VALUE iseqval; + + if (iseq->argc > 1 || iseq->arg_simple == 0) { + /* argument check */ + return 0; + } + + if (iseq->cached_special_block_builder) { + if (iseq->cached_special_block_builder == builder) { + return iseq->cached_special_block; + } + else { + return 0; + } + } + else { + iseq->cached_special_block_builder = (void *)1; + } + + if (iseq->parent_iseq) { + parent = iseq->parent_iseq->self; + } + iseqval = yarv_iseq_new_with_bopt(iseq->node, iseq->name, iseq->file_name, + parent, iseq->type, + GC_GUARDED_PTR(builder)); + if (0) { + printf("%s\n", RSTRING_PTR(iseq_disasm(iseqval))); + } + iseq->cached_special_block = iseqval; + iseq->cached_special_block_builder = builder; + return iseqval; +#else + return 0; +#endif +} + +static NODE * +new_block(NODE * head, NODE * tail) +{ + head = NEW_BLOCK(head); + tail = NEW_BLOCK(tail); + head->nd_next = tail; + return head; +} + +static NODE * +new_ary(NODE * head, NODE * tail) +{ + head = NEW_ARRAY(head); + head->nd_next = tail; + return head; +} + +static NODE * +new_assign(NODE * lnode, NODE * rhs) +{ + switch (nd_type(lnode)) { + case NODE_LASGN:{ + return NEW_NODE(NODE_LASGN, lnode->nd_vid, rhs, lnode->nd_cnt); + /* NEW_LASGN(lnode->nd_vid, rhs); */ + } + case NODE_GASGN:{ + return NEW_GASGN(lnode->nd_vid, rhs); + } + case NODE_DASGN:{ + return NEW_DASGN(lnode->nd_vid, rhs); + } + case NODE_ATTRASGN:{ + NODE *args = 0; + if (lnode->nd_args) { + args = NEW_ARRAY(lnode->nd_args->nd_head); + args->nd_next = NEW_ARRAY(rhs); + args->nd_alen = 2; + } + else { + args = NEW_ARRAY(rhs); + } + + return NEW_ATTRASGN(lnode->nd_recv, + lnode->nd_mid, + args); + } + default: + rb_bug("unimplemented (block inlining): %s", node_name(nd_type(lnode))); + } + return 0; +} + +static NODE * +build_Integer_times_node(yarv_iseq_t *iseq, NODE * node, NODE * lnode, + VALUE param_vars, VALUE local_vars) +{ + /* Special Block for Integer#times + {|e, _self| + _e = e + while(e < _self) + e = _e + redo_point: + BODY + next_point: + _e = _e.succ + end + } + + {|e, _self| + while(e < _self) + BODY + next_point: + e = e.succ + end + } + */ + ID _self = rb_intern("#_self"); + 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; + + node = + NEW_WHILE(NEW_CALL + (NEW_DVAR(e), idLT, new_ary(NEW_DVAR(_self), 0)), + new_block(NEW_OPTBLOCK(node), + NEW_DASGN(e, + NEW_CALL(NEW_DVAR(e), idSucc, 0))), + Qundef); + } + else { + ID _e = rb_intern("#_e"); + ID e = SYM2ID(rb_ary_entry(param_vars, 0)); + NODE *assign; + + rb_ary_push(param_vars, ID2SYM(_self)); + rb_ary_push(local_vars, ID2SYM(_e)); + iseq->argc++; + + if (nd_type(lnode) == NODE_DASGN_CURR) { + assign = NEW_DASGN(e, NEW_DVAR(_e)); + } + else { + assign = new_assign(lnode, NEW_DVAR(_e)); + } + + node = + new_block(NEW_DASGN(_e, NEW_DVAR(e)), + NEW_WHILE(NEW_CALL + (NEW_DVAR(_e), idLT, + new_ary(NEW_DVAR(_self), 0)), + new_block(assign, + new_block(NEW_OPTBLOCK(node), + NEW_DASGN(_e, + NEW_CALL + (NEW_DVAR(_e), + idSucc, 0)))), + Qundef)); + } + return node; +} + +VALUE +yarv_invoke_Integer_times_special_block(VALUE num) +{ + yarv_thread_t *th = GET_THREAD(); + yarv_block_t *orig_block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]); + + if (orig_block && BUILTIN_TYPE(orig_block->iseq) != T_NODE) { + VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq, + build_Integer_times_node); + yarv_iseq_t *tsiseq; + VALUE argv[2], val; + + if (tsiseqval) { + yarv_block_t block = *orig_block; + GetISeqPtr(tsiseqval, tsiseq); + block.iseq = tsiseq; + th->cfp->lfp[0] = GC_GUARDED_PTR(&block); + argv[0] = INT2FIX(0); + argv[1] = num; + val = th_invoke_yield(th, 2, argv); + if (val == Qundef) { + return num; + } + else { + return val; + } + } + } + return Qundef; +} + +static NODE * +build_Range_each_node(yarv_iseq_t *iseq, NODE * node, NODE * lnode, + VALUE param_vars, VALUE local_vars, ID mid) +{ + /* Special Block for Range#each + {|e, _last| + _e = e + while _e < _last + e = _e + next_point: + BODY + redo_point: + _e = _e.succ + end + } + {|e, _last| + while e < _last + BODY + redo_point: + e = e.succ + end + } + */ + ID _last = rb_intern("#_last"); + if (iseq->argc == 0) { + ID e = rb_intern("#e"); + rb_ary_push(param_vars, ID2SYM(e)); + rb_ary_push(param_vars, ID2SYM(_last)); + iseq->argc += 2; + + node = + NEW_WHILE(NEW_CALL(NEW_DVAR(e), mid, new_ary(NEW_DVAR(_last), 0)), + new_block(NEW_OPTBLOCK(node), + NEW_DASGN(e, + NEW_CALL(NEW_DVAR(e), idSucc, 0))), + Qundef); + } + else { + ID _e = rb_intern("#_e"); + ID e = SYM2ID(rb_ary_entry(param_vars, 0)); + NODE *assign; + + rb_ary_push(param_vars, ID2SYM(_last)); + rb_ary_push(local_vars, ID2SYM(_e)); + iseq->argc++; + + if (nd_type(lnode) == NODE_DASGN_CURR) { + assign = NEW_DASGN(e, NEW_DVAR(_e)); + } + else { + assign = new_assign(lnode, NEW_DVAR(_e)); + } + + node = + new_block(NEW_DASGN(_e, NEW_DVAR(e)), + NEW_WHILE(NEW_CALL + (NEW_DVAR(_e), mid, + new_ary(NEW_DVAR(_last), 0)), + new_block(assign, + new_block(NEW_OPTBLOCK(node), + NEW_DASGN(_e, + NEW_CALL + (NEW_DVAR(_e), + idSucc, 0)))), + Qundef)); + } + return node; +} + +static NODE * +build_Range_each_node_LE(yarv_iseq_t *iseq, NODE * node, NODE * lnode, + VALUE param_vars, VALUE local_vars) +{ + return build_Range_each_node(iseq, node, lnode, + param_vars, local_vars, idLE); +} + +static NODE * +build_Range_each_node_LT(yarv_iseq_t *iseq, NODE * node, NODE * lnode, + VALUE param_vars, VALUE local_vars) +{ + return build_Range_each_node(iseq, node, lnode, + param_vars, local_vars, idLT); +} + +VALUE +yarv_invoke_Range_each_special_block(VALUE range, + VALUE beg, VALUE end, int excl) +{ + 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) { + void *builder = + excl ? build_Range_each_node_LT : build_Range_each_node_LE; + VALUE tsiseqval = yarv_iseq_special_block(orig_block->iseq, builder); + yarv_iseq_t *tsiseq; + VALUE argv[2]; + + if (tsiseqval) { + VALUE val; + yarv_block_t block = *orig_block; + GetISeqPtr(tsiseqval, tsiseq); + block.iseq = tsiseq; + th->cfp->lfp[0] = GC_GUARDED_PTR(&block); + argv[0] = beg; + argv[1] = end; + val = th_invoke_yield(th, 2, argv); + if (val == Qundef) { + return range; + } + else { + return val; + } + } + } + return Qundef; +} + + +static NODE * +build_Array_each_node(yarv_iseq_t *iseq, NODE * node, NODE * lnode, + 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)); + NODE *assign; + + rb_ary_push(param_vars, ID2SYM(_self)); + iseq->argc++; + rb_ary_push(local_vars, ID2SYM(_i)); + + if (nd_type(lnode) == NODE_DASGN_CURR) { + assign = NEW_DASGN(e, + NEW_CALL(NEW_DVAR(_self), idAREF, + new_ary(NEW_DVAR(_i), 0))); + } + else { + assign = new_assign(lnode, + NEW_CALL(NEW_DVAR(_self), idAREF, + new_ary(NEW_DVAR(_i), 0))); + } + + 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(assign, + 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; + GetISeqPtr(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; +} diff --git a/call_cfunc.ci b/call_cfunc.ci new file mode 100644 index 0000000..7b8bfe8 --- /dev/null +++ b/call_cfunc.ci @@ -0,0 +1,94 @@ +/* -*-c-*- */ + +/* from ruby1.9/eval.c */ + +static inline VALUE +call_cfunc(func, recv, len, argc, argv) + VALUE (*func) (); + VALUE recv; + int len, argc; + const VALUE *argv; +{ + // printf("len: %d, argc: %d\n", len, argc); + + if (len >= 0 && argc != len) { + rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)", + argc, len); + } + + switch (len) { + case -2: + return (*func) (recv, rb_ary_new4(argc, argv)); + break; + case -1: + return (*func) (argc, argv, recv); + break; + case 0: + return (*func) (recv); + break; + case 1: + return (*func) (recv, argv[0]); + break; + case 2: + return (*func) (recv, argv[0], argv[1]); + break; + case 3: + return (*func) (recv, argv[0], argv[1], argv[2]); + break; + case 4: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3]); + break; + case 5: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4]); + break; + case 6: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5]); + break; + case 7: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6]); + break; + case 8: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7]); + break; + case 9: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8]); + break; + case 10: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8], argv[9]); + break; + case 11: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8], argv[9], + argv[10]); + break; + case 12: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8], argv[9], + argv[10], argv[11]); + break; + case 13: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], + argv[11], argv[12]); + break; + case 14: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], + argv[11], argv[12], argv[13]); + break; + case 15: + return (*func) (recv, argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], + argv[11], argv[12], argv[13], argv[14]); + break; + default: + rb_raise(rb_eArgError, "too many arguments(%d)", len); + break; + } + return Qnil; /* not reached */ +} @@ -56,10 +56,26 @@ rb_class_new(VALUE super) return rb_class_boot(super); } +struct clone_method_data { + st_table *tbl; + VALUE klass; +}; + static int -clone_method(ID mid, NODE *body, st_table *tbl) +clone_method(ID mid, NODE *body, struct clone_method_data *data) { - st_insert(tbl, mid, (st_data_t)NEW_METHOD(body->nd_body, body->nd_noex)); + if (body == 0) { + st_insert(data->tbl, mid, 0); + } + else { + st_insert(data->tbl, mid, + (st_data_t) + NEW_FBODY( + NEW_METHOD(body->nd_body->nd_body, + data->klass, /* TODO */ + body->nd_body->nd_noex), + 0)); + } return ST_CONTINUE; } @@ -82,9 +98,11 @@ rb_mod_init_copy(VALUE clone, VALUE orig) st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0); } if (RCLASS(orig)->m_tbl) { - RCLASS(clone)->m_tbl = st_init_numtable(); + struct clone_method_data data; + data.tbl = RCLASS(clone)->m_tbl = st_init_numtable(); + data.klass = clone; st_foreach(RCLASS(orig)->m_tbl, clone_method, - (st_data_t)RCLASS(clone)->m_tbl); + (st_data_t)&data); } return clone; @@ -111,6 +129,7 @@ rb_singleton_class_clone(VALUE obj) if (!FL_TEST(klass, FL_SINGLETON)) return klass; else { + struct clone_method_data data; /* copy singleton(unnamed) class */ NEWOBJ(clone, struct RClass); OBJSETUP(clone, 0, RBASIC(klass)->flags); @@ -129,8 +148,10 @@ rb_singleton_class_clone(VALUE obj) clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl); } clone->m_tbl = st_init_numtable(); + data.tbl = clone->m_tbl; + data.klass = (VALUE)clone; st_foreach(RCLASS(klass)->m_tbl, clone_method, - (st_data_t)clone->m_tbl); + (st_data_t)&data); rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); FL_SET(clone, FL_SINGLETON); return (VALUE)clone; @@ -359,27 +380,27 @@ rb_include_module(VALUE klass, VALUE module) OBJ_INFECT(klass, module); c = klass; while (module) { - int superclass_seen = Qfalse; + int superclass_seen = Qfalse; if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl) rb_raise(rb_eArgError, "cyclic include detected"); - /* ignore if the module included already in superclasses */ - for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) { - switch (BUILTIN_TYPE(p)) { - case T_ICLASS: - if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) { - if (!superclass_seen) { - c = p; /* move insertion point */ - } - goto skip; - } - break; - case T_CLASS: - superclass_seen = Qtrue; - break; - } - } - c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super); + /* ignore if the module included already in superclasses */ + for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) { + switch (BUILTIN_TYPE(p)) { + case T_ICLASS: + if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) { + if (!superclass_seen) { + c = p; /* move insertion point */ + } + goto skip; + } + break; + case T_CLASS: + superclass_seen = Qtrue; + break; + } + } + c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super); changed = 1; skip: module = RCLASS(module)->super; @@ -492,6 +513,7 @@ static int ins_methods_push(ID name, long type, VALUE ary, long visi) { if (type == -1) return ST_CONTINUE; + switch (visi) { case NOEX_PRIVATE: case NOEX_PROTECTED: @@ -544,10 +566,17 @@ method_entry(ID key, NODE *body, st_table *list) { long type; - if (key == ID_ALLOCATOR) return ST_CONTINUE; + if (key == ID_ALLOCATOR) { + return ST_CONTINUE; + } + if (!st_lookup(list, key, 0)) { - if (!body->nd_body) type = -1; /* none */ - else type = VISI(body->nd_noex); + if (body ==0 || !body->nd_body->nd_body) { + type = -1; /* none */ + } + else { + type = VISI(body->nd_body->nd_noex); + } st_add_direct(list, key, type); } return ST_CONTINUE; @@ -1,15 +1,11 @@ bin: $(PROGRAM) $(WPROGRAM) -lib: $(LIBRUBY) -dll: $(LIBRUBY_SO) +lib: $(LIBRUBY); +dll: $(LIBRUBY_SO); RUBYOPT = -STATIC_RUBY = static-ruby - EXTCONF = extconf.rb RBCONFIG = ./.rbconfig.time -LIBRUBY_EXTS = ./.libruby-with-ext.time -RDOCOUT = $(EXTOUT)/rdoc DMYEXT = dmyext.$(OBJEXT) MAINOBJ = main.$(OBJEXT) @@ -28,6 +24,9 @@ OBJS = array.$(OBJEXT) \ error.$(OBJEXT) \ euc_jp.$(OBJEXT) \ eval.$(OBJEXT) \ + eval_load.$(OBJEXT) \ + eval_proc.$(OBJEXT) \ + eval_thread.$(OBJEXT) \ file.$(OBJEXT) \ gc.$(OBJEXT) \ hash.$(OBJEXT) \ @@ -61,218 +60,94 @@ OBJS = array.$(OBJEXT) \ util.$(OBJEXT) \ variable.$(OBJEXT) \ version.$(OBJEXT) \ + blockinlining.$(OBJEXT) \ + compile.$(OBJEXT) \ + debug.$(OBJEXT) \ + iseq.$(OBJEXT) \ + vm.$(OBJEXT) \ + vm_dump.$(OBJEXT) \ + yarvcore.$(OBJEXT) \ + thread.$(OBJEXT) \ $(MISSING) SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \ - --extout="$(EXTOUT)" \ --make="$(MAKE)" \ --mflags="$(MFLAGS)" \ --make-flags="$(MAKEFLAGS)" -EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) -- -INSTRUBY_ARGS = $(SCRIPT_ARGS) --installed-list $(INSTALLED_LIST) - -PRE_LIBRUBY_UPDATE = $(MINIRUBY) -e 'ARGV[1] or File.unlink(ARGV[0]) rescue nil' -- \ - $(LIBRUBY_EXTS) $(LIBRUBY_SO_UPDATE) - -TESTSDIR = $(srcdir)/test -TESTWORKDIR = testwork +EXTMK_ARGS = $(SCRIPT_ARGS) --extout="$(EXTOUT)" --extension $(EXTS) --extstatic $(EXTSTATIC) -- all: $(MKFILES) $(PREP) $(RBCONFIG) $(LIBRUBY) - @$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) + $(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) + prog: $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT) $(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP) -$(LIBRUBY_A): $(OBJS) $(DMYEXT) $(ARCHFILE) +$(LIBRUBY_A): $(OBJS) $(DMYEXT) -$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP) $(LIBRUBY_SO_UPDATE) +$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP) $(ARCHFILE) -$(LIBRUBY_EXTS): - @exit > $@ - -$(STATIC_RUBY)$(EXEEXT): $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A) +static-ruby: $(MAINOBJ) $(EXTOBJS) $(LIBRUBY_A) @$(RM) $@ - $(PURIFY) $(CC) $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)$@ $(LDFLAGS) $(XLDFLAGS) + $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY_A) $(LIBS) $(OUTFLAG)$@ -ruby.imp: $(OBJS) - @$(NM) -Pgp $(OBJS) | awk 'BEGIN{print "#!"}; $$2~/^[BD]$$/{print $$1}' | sort -u -o $@ +ruby.imp: $(LIBRUBY_A) + @$(NM) -Pgp $(LIBRUBY_A) | awk 'BEGIN{print "#!"}; $$2~/^[BD]$$/{print $$1}' | sort -u -o $@ install: install-nodoc $(RDOCTARGET) install-all: install-nodoc install-doc -install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc -pre-install-nodoc:: pre-install-local pre-install-ext -do-install-nodoc: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --mantype="$(MANTYPE)" -post-install-nodoc:: post-install-local post-install-ext - +install-nodoc: install-local install-ext install-local: pre-install-local do-install-local post-install-local -pre-install-local:: pre-install-bin pre-install-lib pre-install-man -do-install-local: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)" -post-install-local:: post-install-bin post-install-lib post-install-man - install-ext: pre-install-ext do-install-ext post-install-ext -pre-install-ext:: pre-install-ext-arch pre-install-ext-comm -do-install-ext: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=ext -post-install-ext:: post-install-ext-arch post-install-ext-comm - -install-arch: pre-install-arch do-install-arch post-install-arch -pre-install-arch:: pre-install-bin pre-install-ext-arch -do-install-arch: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=bin --install=ext-arch -post-install-arch:: post-install-bin post-install-ext-arch - -install-comm: pre-install-comm do-install-comm post-install-comm -pre-install-comm:: pre-install-lib pre-install-ext-comm pre-install-man -do-install-comm: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man -post-install-comm:: post-install-lib post-install-ext-comm post-install-man - -install-bin: pre-install-bin do-install-bin post-install-bin -pre-install-bin:: install-prereq -do-install-bin: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=bin -post-install-bin:: - @$(NULLCMD) - -install-lib: pre-install-lib do-install-lib post-install-lib -pre-install-lib:: install-prereq -do-install-lib: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=lib -post-install-lib:: - @$(NULLCMD) - -install-ext-comm: pre-install-ext-comm do-install-ext-comm post-install-ext-comm -pre-install-ext-comm:: install-prereq -do-install-ext-comm: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=ext-comm -post-install-ext-comm:: - @$(NULLCMD) - -install-ext-arch: pre-install-ext-arch do-install-ext-arch post-install-ext-arch -pre-install-ext-arch:: install-prereq -do-install-ext-arch: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=ext-arch -post-install-ext-arch:: - @$(NULLCMD) - -install-man: pre-install-man do-install-man post-install-man -pre-install-man:: install-prereq -do-install-man: - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)" -post-install-man:: - @$(NULLCMD) - -what-where: no-install -no-install: no-install-nodoc no-install-doc -what-where-all: no-install-all -no-install-all: no-install-nodoc - -what-where-nodoc: no-install-nodoc -no-install-nodoc: pre-no-install-nodoc dont-install-nodoc post-no-install-nodoc -pre-no-install-nodoc:: pre-no-install-local pre-no-install-ext -dont-install-nodoc: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --mantype="$(MANTYPE)" -post-no-install-nodoc:: post-no-install-local post-no-install-ext -what-where-local: no-install-local -no-install-local: pre-no-install-local dont-install-local post-no-install-local -pre-no-install-local:: pre-no-install-bin pre-no-install-lib pre-no-install-man -dont-install-local: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)" -post-no-install-local:: post-no-install-bin post-no-install-lib post-no-install-man +do-install-local: $(RBCONFIG) + $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --mantype="$(MANTYPE)" +do-install-ext: $(RBCONFIG) + $(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) install + +install-bin: $(RBCONFIG) + $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=bin +install-lib: $(RBCONFIG) + $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=lib +install-man: $(RBCONFIG) + $(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=man --mantype="$(MANTYPE)" +what-where-all no-install-all: no-install no-install-doc +what-where no-install: no-install-local no-install-ext +what-where-local: no-install-local +no-install-local: $(RBCONFIG) + $(MINIRUBY) $(srcdir)/instruby.rb -n $(SCRIPT_ARGS) --mantype="$(MANTYPE)" what-where-ext: no-install-ext -no-install-ext: pre-no-install-ext dont-install-ext post-no-install-ext -pre-no-install-ext:: pre-no-install-ext-arch pre-no-install-ext-comm -dont-install-ext: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=ext -post-no-install-ext:: post-no-install-ext-arch post-no-install-ext-comm - -what-where-arch: no-install-arch -no-install-arch: pre-no-install-arch dont-install-arch post-no-install-arch -pre-no-install-arch:: pre-no-install-bin pre-no-install-ext-arch -dont-install-arch: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=bin --install=ext-arch -post-no-install-arch:: post-no-install-lib post-no-install-man post-no-install-ext-arch - -what-where-comm: no-install-comm -no-install-comm: pre-no-install-comm dont-install-comm post-no-install-comm -pre-no-install-comm:: pre-no-install-lib pre-no-install-ext-comm pre-no-install-man -dont-install-comm: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man -post-no-install-comm:: post-no-install-lib post-no-install-ext-comm post-no-install-man - -what-where-bin: no-install-bin -no-install-bin: pre-no-install-bin dont-install-bin post-no-install-bin -pre-no-install-bin:: install-prereq -dont-install-bin: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=bin -post-no-install-bin:: - @$(NULLCMD) - -what-where-lib: no-install-lib -no-install-lib: pre-no-install-lib dont-install-lib post-no-install-lib -pre-no-install-lib:: install-prereq -dont-install-lib: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=lib -post-no-install-lib:: - @$(NULLCMD) - -what-where-ext-comm: no-install-ext-comm -no-install-ext-comm: pre-no-install-ext-comm dont-install-ext-comm post-no-install-ext-comm -pre-no-install-ext-comm:: install-prereq -dont-install-ext-comm: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=ext-comm -post-no-install-ext-comm:: - @$(NULLCMD) - -what-where-ext-arch: no-install-ext-arch -no-install-ext-arch: pre-no-install-ext-arch dont-install-ext-arch post-no-install-ext-arch -pre-no-install-ext-arch:: install-prereq -dont-install-ext-arch: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=ext-arch -post-no-install-ext-arch:: - @$(NULLCMD) - -what-where-man: no-install-man -no-install-man: pre-no-install-man dont-install-man post-no-install-man -pre-no-install-man:: install-prereq -dont-install-man: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)" -post-no-install-man:: - @$(NULLCMD) - -install-doc: rdoc pre-install-doc do-install-doc post-install-doc -pre-install-doc:: install-prereq -do-install-doc: $(PROGRAM) - $(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)" -post-install-doc:: - @$(NULLCMD) +no-install-ext: $(RBCONFIG) + $(MINIRUBY) $(srcdir)/ext/extmk.rb -n $(EXTMK_ARGS) install -rdoc: $(PROGRAM) PHONY +install-doc: pre-install-doc do-install-doc post-install-doc +do-install-doc: $(PROGRAM) @echo Generating RDoc documentation - $(RUNRUBY) "$(srcdir)/bin/rdoc" --all --ri --op "$(RDOCOUT)" "$(srcdir)" + $(RUNRUBY) "$(srcdir)/bin/rdoc" --all --ri --op "$(RIDATADIR)" "$(srcdir)" + +pre-install: pre-install-local pre-install-ext +pre-install-local:: PHONY +pre-install-ext:: PHONY +pre-install-doc:: PHONY -what-where-doc: no-install-doc -no-install-doc: pre-no-install-doc dont-install-doc post-no-install-doc -pre-no-install-doc:: install-prereq -dont-install-doc:: - $(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)" -post-no-install-doc:: - @$(NULLCMD) +post-install: post-install-local post-install-ext +post-install-local:: PHONY +post-install-ext:: PHONY +post-install-doc:: PHONY -install-prereq: - @exit > $(INSTALLED_LIST) +# no ext +# clean: clean-ext clean-local +clean: clean-local -clean: clean-ext clean-local clean-local:: @$(RM) $(OBJS) $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES) - @$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) $(ARCHFILE) .*.time + @$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) $(ARCHFILE) + @$(RM) *.inc + clean-ext: @-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) clean @@ -292,15 +167,15 @@ check: test test-all test: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY @$(MINIRUBY) $(srcdir)/rubytest.rb -test-all: - $(RUNRUBY) "$(srcdir)/test/runner.rb" --basedir="$(TESTSDIR)" --runner=$(TESTUI) $(TESTS) +test-all: miniruby$(EXEEXT) ruby + $(RUNRUBY) -C "$(srcdir)/test" runner.rb --runner=$(TESTUI) $(TESTS) extconf: $(MINIRUBY) -I$(srcdir)/lib -run -e mkdir -- -p "$(EXTCONFDIR)" $(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS) $(RBCONFIG): $(srcdir)/mkconfig.rb config.status $(PREP) - @$(MINIRUBY) $(srcdir)/mkconfig.rb -timestamp=$@ \ + $(MINIRUBY) $(srcdir)/mkconfig.rb -timestamp=$@ \ -install_name=$(RUBY_INSTALL_NAME) \ -so_name=$(RUBY_SO_NAME) rbconfig.rb @@ -336,8 +211,6 @@ nt.$(OBJEXT): {$(VPATH)}nt.c x68.$(OBJEXT): {$(VPATH)}x68.c os2.$(OBJEXT): {$(VPATH)}os2.c dl_os2.$(OBJEXT): {$(VPATH)}dl_os2.c -ia64.$(OBJEXT): {$(VPATH)}ia64.s - $(CC) $(CFLAGS) -c $< # when I use -I., there is confliction at "OpenFile" # so, set . into environment varible "include" @@ -374,13 +247,41 @@ enumerator.$(OBJEXT): {$(VPATH)}enumerator.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}env.h {$(VPATH)}st.h + {$(VPATH)}st.h vm_opts.h euc_jp.$(OBJEXT): {$(VPATH)}euc_jp.c {$(VPATH)}regenc.h \ {$(VPATH)}oniguruma.h -eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}ruby.h config.h \ + +eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_intern.h \ + {$(VPATH)}eval_method.h {$(VPATH)}eval_safe.h {$(VPATH)}eval_jump.h \ + {$(VPATH)}ruby.h config.h {$(VPATH)}yarvcore.h \ + {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ + {$(VPATH)}node.h {$(VPATH)}util.h \ + {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}yarv.h +eval_load.$(OBJEXT): {$(VPATH)}eval_load.c {$(VPATH)}eval_intern.h \ + {$(VPATH)}ruby.h config.h \ + {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ + {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}yarvcore.h \ + {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}yarv.h +eval_thread.$(OBJEXT): {$(VPATH)}eval_thread.c {$(VPATH)}eval_intern.h \ + {$(VPATH)}ruby.h config.h {$(VPATH)}yarvcore.h \ + {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ + {$(VPATH)}node.h {$(VPATH)}util.h \ + {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}yarv.h +eval_proc.$(OBJEXT): {$(VPATH)}eval_proc.c {$(VPATH)}eval_intern.h \ + {$(VPATH)}ruby.h config.h {$(VPATH)}yarvcore.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}node.h {$(VPATH)}env.h {$(VPATH)}util.h \ - {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h + {$(VPATH)}node.h {$(VPATH)}util.h \ + {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h {$(VPATH)}yarv.h + +thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \ + {$(VPATH)}thread_win32.h {$(VPATH)}thread_pthread.h \ + {$(VPATH)}thread_win32.ci {$(VPATH)}thread_pthread.ci \ + {$(VPATH)}ruby.h config.h \ + {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ + {$(VPATH)}node.h {$(VPATH)}util.h \ + {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.h \ + {$(VPATH)}yarv.h {$(VPATH)}yarvcore.h + file.$(OBJEXT): {$(VPATH)}file.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}rubyio.h {$(VPATH)}rubysig.h {$(VPATH)}util.h \ @@ -388,8 +289,7 @@ file.$(OBJEXT): {$(VPATH)}file.c {$(VPATH)}ruby.h config.h \ gc.$(OBJEXT): {$(VPATH)}gc.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}node.h \ - {$(VPATH)}env.h {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}regint.h \ - {$(VPATH)}oniguruma.h + {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}yarvcore.h hash.$(OBJEXT): {$(VPATH)}hash.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ {$(VPATH)}st.h {$(VPATH)}util.h {$(VPATH)}rubysig.h @@ -406,7 +306,7 @@ marshal.$(OBJEXT): {$(VPATH)}marshal.c {$(VPATH)}ruby.h config.h \ math.$(OBJEXT): {$(VPATH)}math.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h numeric.$(OBJEXT): {$(VPATH)}numeric.c {$(VPATH)}ruby.h config.h \ - {$(VPATH)}env.h {$(VPATH)}defines.h {$(VPATH)}intern.h \ + {$(VPATH)}defines.h {$(VPATH)}intern.h \ {$(VPATH)}missing.h object.$(OBJEXT): {$(VPATH)}object.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ @@ -415,7 +315,7 @@ pack.$(OBJEXT): {$(VPATH)}pack.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}env.h {$(VPATH)}node.h {$(VPATH)}st.h \ + {$(VPATH)}node.h {$(VPATH)}st.h \ {$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c prec.$(OBJEXT): {$(VPATH)}prec.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h @@ -428,7 +328,7 @@ range.$(OBJEXT): {$(VPATH)}range.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h re.$(OBJEXT): {$(VPATH)}re.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}regint.h {$(VPATH)}oniguruma.h + {$(VPATH)}re.h {$(VPATH)}regex.h regcomp.$(OBJEXT): {$(VPATH)}regcomp.c {$(VPATH)}oniguruma.h \ {$(VPATH)}regint.h {$(VPATH)}regparse.h {$(VPATH)}regenc.h config.h regenc.$(OBJEXT): {$(VPATH)}regenc.c {$(VPATH)}regint.h \ @@ -444,7 +344,7 @@ ruby.$(OBJEXT): {$(VPATH)}ruby.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}dln.h {$(VPATH)}node.h {$(VPATH)}util.h signal.$(OBJEXT): {$(VPATH)}signal.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}rubysig.h + {$(VPATH)}rubysig.h {$(VPATH)}yarvcore.h sjis.$(OBJEXT): {$(VPATH)}sjis.c {$(VPATH)}regenc.h \ {$(VPATH)}oniguruma.h config.h sprintf.$(OBJEXT): {$(VPATH)}sprintf.c {$(VPATH)}ruby.h config.h \ @@ -452,7 +352,7 @@ sprintf.$(OBJEXT): {$(VPATH)}sprintf.c {$(VPATH)}ruby.h config.h \ st.$(OBJEXT): {$(VPATH)}st.c config.h {$(VPATH)}st.h string.$(OBJEXT): {$(VPATH)}string.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}regint.h {$(VPATH)}oniguruma.h + {$(VPATH)}re.h {$(VPATH)}regex.h struct.$(OBJEXT): {$(VPATH)}struct.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h time.$(OBJEXT): {$(VPATH)}time.c {$(VPATH)}ruby.h config.h \ @@ -464,7 +364,112 @@ util.$(OBJEXT): {$(VPATH)}util.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}util.h variable.$(OBJEXT): {$(VPATH)}variable.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}env.h {$(VPATH)}node.h {$(VPATH)}st.h {$(VPATH)}util.h + {$(VPATH)}node.h {$(VPATH)}st.h {$(VPATH)}util.h version.$(OBJEXT): {$(VPATH)}version.c {$(VPATH)}ruby.h config.h \ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \ - {$(VPATH)}version.h + {$(VPATH)}version.h {$(VPATH)}yarv_version.h + +compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}yarvcore.h \ + {$(VPATH)}compile.h {$(VPATH)}debug.h \ + insns.inc insns_info.inc optinsn.inc opt_sc.inc optunifs.inc vm_opts.h +iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}yarvcore.h {$(VPATH)}debug.h vm_opts.h +vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}vm.h {$(VPATH)}insnhelper.h \ + {$(VPATH)}yarvcore.h {$(VPATH)}debug.h \ + {$(VPATH)}vm_evalbody.ci {$(VPATH)}call_cfunc.ci \ + insns.inc vm.inc vmtc.inc vm_macro.inc vm_opts.h {$(VPATH)}eval_intern.h +vm_dump.$(OBJEXT): {$(VPATH)}yarvcore.h {$(VPATH)}vm.h +yarvcore.$(OBJEXT): {$(VPATH)}yarvcore.c {$(VPATH)}yarvcore.h \ + {$(VPATH)}yarv_version.h {$(VPATH)}debug.h +debug.$(OBJEXT): {$(VPATH)}debug.h +blockinlining.$(OBJEXT): {$(VPATH)}yarv.h {$(VPATH)}yarvcore.h vm_opts.h + + +BASERUBY = ruby + +INSNS2VMOPT = $(CPPFLAGS) --srcdir=$(srcdir) + +minsns.inc: + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) + +opt_sc.inc: + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) + +optinsn.inc: + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) optinsn.inc + +optunifs.inc: + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) optunifs.inc + +insns.inc: + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) + +vmtc.inc: + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) vmtc.inc + +vm.inc: $(srcdir)/insns.def + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) vm.inc + +vm_macro.inc: $(srcdir)/vm_macro.def + $(BASERUBY) $(srcdir)/rb/insns2vm.rb $(INSNS2VMOPT) vm_macro.inc + +vm_opts.h: $(srcdir)/vm_opts.h.base + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) + +incs: + $(BASERUBY) $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) + +docs: + $(BASERUBY) -I$(srcdir) $(srcdir)/tool/makedocs.rb $(INSNS2VMOPT) + +yarv-test-all: miniruby$(EXEEXT) + $(BASERUBY) -I$(srcdir) $(srcdir)/yarvtest/runner.rb $(OPT) yarv=$(MINIRUBY) ruby=$(BASERUBY) + +yarv-test-each: miniruby$(EXEEXT) + $(BASERUBY) -I$(srcdir) $(srcdir)/yarvtest/test_$(ITEM).rb $(OPT) yarv=$(MINIRUBY) ruby=$(BASERUBY) + +allload: miniruby$(EXEEXT) + $(MINIRUBY) -I$(srcdir) $(srcdir)/tool/allload.rb `$(BASERUBY) -rrbconfig -e 'print Config::CONFIG["rubylibdir"]'` + +run: miniruby$(EXEEXT) + $(MINIRUBY) -I$(srcdir)/lib $(srcdir)/test.rb $(RUNOPT) + +runruby: $(RUBY) + ./$(RUBY) -I$(srcdir)/lib -I. $(srcdir)/tool/runruby.rb $(srcdir)/test.rb + +parse: miniruby$(EXEEXT) + $(MINIRUBY) $(srcdir)/tool/parse.rb $(srcdir)/test.rb + +benchmark: $(RUBY) + $(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb $(OPT) $(ITEMS) --yarv-program=./$(PROGRAM) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib + +tbench: prog + $(BASERUBY) -I$(srcdir) -I$(srcdir)/lib $(srcdir)/benchmark/run_rite.rb bmx $(OPT) --yarv-program=./$(PROGRAM) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib + +bench-each: $(RUBY) + $(BASERUBY) -I$(srcdir) $(srcdir)/benchmark/run_rite.rb bm_$(ITEM) $(OPT) --yarv-program=./$(RUBY) --ruby-program=$(BASERUBY) --opts=-I$(srcdir)/lib + +aotc: + $(RUBY) -I$(srcdir) -I. $(srcdir)/tool/aotcompile.rb $(INSNS2VMOPT) + +# for GCC +vmasm: + $(CC) $(CFLAGS) $(CPPFLAGS) -S $(srcdir)/vm.c + +# vm.o : CFLAGS += -fno-crossjumping + +run.gdb: + echo b debug_breakpoint > run.gdb + echo handle SIGINT nostop + echo handle SIGPIPE nostop + echo run >> run.gdb + +gdb: miniruby$(EXEEXT) run.gdb + gdb -x run.gdb --quiet --args $(MINIRUBY) -I$(srcdir)/lib $(srcdir)/test.rb + +# Intel VTune + +vtune: miniruby$(EXEEXT) + vtl activity -c sampling -app ".\miniruby$(EXEEXT)","-I$(srcdir)/lib $(srcdir)/test.rb" run + vtl view -hf -mn miniruby$(EXEEXT) -sum -sort -cd + vtl view -ha -mn miniruby$(EXEEXT) -sum -sort -cd | $(BASERUBY) $(srcdir)/tool/vtlh.rb > ha.lines + diff --git a/compile.c b/compile.c new file mode 100644 index 0000000..025e655 --- /dev/null +++ b/compile.c @@ -0,0 +1,4914 @@ +/********************************************************************** + + compile.c - ruby node tree -> yarv instruction sequence + + $Author$ + $Date$ + created at: 04/01/01 03:42:15 JST + + Copyright (C) 2004-2006 Koichi Sasada + +**********************************************************************/ + +#include "ruby.h" +#include "node.h" + +#include "yarvcore.h" +#include "compile.h" +#include "insns.inc" +#include "insns_info.inc" + + +#ifdef HAVE_STDARG_PROTOTYPES +#include <stdarg.h> +#define va_init_list(a,b) va_start(a,b) +#else +#include <varargs.h> +#define va_init_list(a,b) va_start(a) +#endif + +/* types */ + +#define ISEQ_ELEMENT_NONE INT2FIX(0x00) +#define ISEQ_ELEMENT_LABEL INT2FIX(0x01) +#define ISEQ_ELEMENT_INSN INT2FIX(0x02) +#define ISEQ_ELEMENT_SEQ INT2FIX(0x03) + +typedef struct iseq_link_element { + int type; + struct iseq_link_element *next; + struct iseq_link_element *prev; +} LINK_ELEMENT; + +typedef struct iseq_link_anchor { + LINK_ELEMENT anchor; + LINK_ELEMENT *last; +} LINK_ANCHOR; + +typedef struct iseq_label_data { + LINK_ELEMENT link; + int label_no; + int position; + int sc_state; + int set; + int sp; +} LABEL; + +typedef struct iseq_insn_data { + LINK_ELEMENT link; + int insn_id; + int line_no; + int operand_size; + int sc_state; + 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; +static long gl_tmp = 0; +static void debug_list(LINK_ANCHOR *anchor); +#endif + +static void dump_disasm_anchor(LINK_ANCHOR *anc); +static void dump_disasm_list(LINK_ELEMENT *elem); + +static int insn_data_length(INSN *iobj); +static int insn_data_line_no(INSN *iobj); +static int calc_sp_depth(int depth, INSN *iobj); +static int insn_ret_num(int insn); + +static void ADD_ELEM(LINK_ANCHOR *anchor, LINK_ELEMENT *elem); + +static INSN *new_insn_body(yarv_iseq_t *iseq, int line_no, + int insn_id, int argc, ...); +static LABEL *new_label_body(yarv_iseq_t *iseq, int line); + +static int iseq_compile_each(yarv_iseq_t *iseq, LINK_ANCHOR *anchor, + NODE * n, int); +static int iseq_setup(yarv_iseq_t *iseq, LINK_ANCHOR *anchor); + +static int iseq_optimize(yarv_iseq_t *iseq, LINK_ANCHOR *anchor); +static int iseq_insns_unification(yarv_iseq_t *iseq, LINK_ANCHOR *anchor); +static int set_sequence_stackcaching(yarv_iseq_t *iseq, LINK_ANCHOR *anchor); +static int set_sequence(yarv_iseq_t *iseq, LINK_ANCHOR *anchor); + +static int set_exception_table(yarv_iseq_t *iseq); +static int set_localtbl(yarv_iseq_t *iseq, ID *tbl); +static int set_localtbl_eval(yarv_iseq_t *iseq, ID *tbl); +static int set_arguments(yarv_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * node); +static NODE *set_block_local_tbl(yarv_iseq_t *iseq, NODE * node, + LINK_ANCHOR *anchor); +static int set_exception_tbl(yarv_iseq_t *iseq); +static int set_optargs_table(yarv_iseq_t *iseq); + +static int +iseq_add_mark_object(yarv_iseq_t *iseq, VALUE v) +{ + rb_ary_push(iseq->iseq_mark_ary, v); + return COMPILE_OK; +} + +static int +iseq_add_mark_object_compile_time(yarv_iseq_t *iseq, VALUE v) +{ + rb_ary_push(iseq->compile_data->mark_ary, v); + return COMPILE_OK; +} + + +#include "optinsn.inc" + +#if OPT_INSTRUCTIONS_UNIFICATION +#include "optunifs.inc" +#endif + +VALUE +iseq_compile(VALUE self, NODE *narg) +{ + DECL_ANCHOR(list_anchor); + yarv_iseq_t *iseq; + NODE *node = (NODE *) narg; + GetISeqPtr(self, iseq); + + debugs("[compile step 1 (traverse each node)]\n"); + + + iseq->node = node; + + if (iseq->type == ISEQ_TYPE_BLOCK) { + node = set_block_local_tbl(iseq, node, list_anchor); + } + + if (node && nd_type(node) == NODE_SCOPE) { + /* with node scope */ + NODE *sn_body = node->nd_next; /* sn: scope node */ + NODE *ndargs = 0; + + if (iseq->type != ISEQ_TYPE_BLOCK) { + set_localtbl(iseq, ((NODE *) node)->nd_tbl); + } + + if (sn_body) { + switch (nd_type(sn_body)) { + case NODE_BLOCK: + if (nd_type(sn_body->nd_head) == NODE_ARGS) { + /* some method attribute process */ + ndargs = sn_body->nd_head; + set_arguments(iseq, list_anchor, ndargs); + + /* with sn_body->nd_head */ + if (iseq->type == ISEQ_TYPE_METHOD) { + COMPILE(list_anchor, "normal method", + sn_body->nd_next); + } + else if (iseq->type == ISEQ_TYPE_CLASS) { + COMPILE(list_anchor, "class/module", + sn_body->nd_next); + } + else { + rb_bug("must be class or method"); + } + } + else { + /* normal block */ + if (iseq->type == ISEQ_TYPE_CLASS) { + COMPILE(list_anchor, "class/module", sn_body); + } + else if (iseq->type == ISEQ_TYPE_BLOCK) { + COMPILE(list_anchor, "normal block", sn_body); + } + else { + rb_bug("must be class or block"); + } + } + break; + case NODE_ARGS: + /* empty method */ + /* some method attribute process */ + debugs("empty method\n"); + + set_arguments(iseq, list_anchor, sn_body); + ADD_INSN(list_anchor, nd_line(sn_body), putnil); + break; + + default: + COMPILE(list_anchor, "other scope", sn_body); + break; + } + } + else { + /* sn_body == 0 */ + ADD_INSN(list_anchor, 0, putnil); + } + } + else { + if (iseq->type == ISEQ_TYPE_BLOCK) { + VALUE tmp; + LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0); + LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0); + + ADD_LABEL(list_anchor, iseq->compile_data->start_label); + COMPILE(list_anchor, "block body", node); + ADD_LABEL(list_anchor, iseq->compile_data->end_label); + + /* wide range catch handler must put at last */ + ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start); + ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end); + } + else if (iseq->type == ISEQ_TYPE_TOP) { + set_localtbl(iseq, GET_THREAD()->top_local_tbl); + COMPILE(list_anchor, "top level node", node); + } + else if (iseq->type == ISEQ_TYPE_EVAL) { + set_localtbl_eval(iseq, GET_THREAD()->top_local_tbl); + COMPILE(list_anchor, "eval node", node); + } + else if (iseq->type == ISEQ_TYPE_RESCUE) { + set_exception_tbl(iseq); + COMPILE(list_anchor, "rescue", node); + } + else if (iseq->type == ISEQ_TYPE_ENSURE) { + set_exception_tbl(iseq); + COMPILE_POPED(list_anchor, "ensure", node); + } + else if (iseq->type == ISEQ_TYPE_DEFINED_GUARD) { + COMPILE(list_anchor, "defined guard", node); + } + else if (node == 0) { + COMPILE(list_anchor, "nil", node); + } + else { + rb_bug("unknown scope"); + } + } + + GC_CHECK(); + + if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) { + ADD_INSN2(list_anchor, 0, getdynamic, INT2FIX(1), INT2FIX(0)); + ADD_INSN1(list_anchor, 0, throw, INT2FIX(0) /* continue throw */ ); + } + else { + ADD_INSN(list_anchor, iseq->compile_data->last_line, leave); + } + + return iseq_setup(iseq, list_anchor); +} + +VALUE th_eval(void *); + +static int +iseq_translate_direct_threaded_code(yarv_iseq_t *iseq) +{ +#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE + +#if OPT_DIRECT_THREADED_CODE + void **table = (void **)th_eval(0); +#else + extern void **insns_address_table(); + void **table = get_insns_address_table(); +#endif + int i; + + iseq->iseq_encoded = ALLOC_N(VALUE, iseq->size); + MEMCPY(iseq->iseq_encoded, iseq->iseq, VALUE, iseq->size); + + for (i = 0; i < iseq->size; /* */ ) { + int insn = iseq->iseq_encoded[i]; + int len = insn_len(insn); + iseq->iseq_encoded[i] = (VALUE)table[insn]; + i += len; + } +#else + iseq->iseq_encoded = iseq->iseq; +#endif + return COMPILE_OK; +} + +/*********************************************/ +/* definition of data structure for compiler */ +/*********************************************/ + + +static void * +compile_data_alloc(yarv_iseq_t *iseq, size_t size) +{ + void *ptr = 0; + struct iseq_compile_data_storage *storage = + iseq->compile_data->storage_current; + + if (storage->pos + size > storage->size) { + unsigned long alloc_size = storage->size * 2; + + retry: + if (alloc_size < size) { + alloc_size *= 2; + goto retry; + } + storage->next = (void *)ALLOC_N(char, alloc_size + + sizeof(struct + iseq_compile_data_storage)); + storage = iseq->compile_data->storage_current = storage->next; + + storage->next = 0; + storage->pos = 0; + storage->size = alloc_size; + storage->buff = (char *)(&storage->buff + 1); + } + + ptr = (void *)&storage->buff[storage->pos]; + storage->pos += size; + return ptr; +} + +static INSN * +compile_data_alloc_insn(yarv_iseq_t *iseq) +{ + return (INSN *)compile_data_alloc(iseq, sizeof(INSN)); +} + +static LABEL * +compile_data_alloc_label(yarv_iseq_t *iseq) +{ + return (LABEL *)compile_data_alloc(iseq, sizeof(LABEL)); +} + +/* + * To make Array to LinkedList, use link_anchor + */ + +static void +verify_list(char *info, LINK_ANCHOR *anchor) +{ +#if CPDEBUG > 0 + int flag = 0; + LINK_ELEMENT *list = anchor->anchor.next, *plist = &anchor->anchor; + + while (list) { + if (plist != list->prev) { + flag += 1; + } + plist = list; + list = list->next; + } + + if (anchor->last != plist && anchor->last != 0) { + flag |= 0x70000; + } + + if (flag != 0) { + rb_bug("list verify error: %08x (%s)", flag, info); + } +#endif +} + +/* + * elem1, elem2 => elem1, elem2, elem + */ +static void +ADD_ELEM(LINK_ANCHOR *anchor, LINK_ELEMENT *elem) +{ + elem->prev = anchor->last; + anchor->last->next = elem; + anchor->last = elem; + verify_list("add", anchor); +} + +/*******************************************/ +#if 0 +/* + * elem1, elemX => elem1, elem2, elemX + */ +static void +INSERT_ELEM_NEXT(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2) +{ + elem2->next = elem1->next; + elem2->prev = elem1; + elem1->next = elem2; + if (elem2->next) { + elem2->next->prev = elem2; + } +} +#endif + +/* + * elemX, elem1 => elemX, elem2, elem1 + */ +static void +INSERT_ELEM_PREV(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2) +{ + elem2->prev = elem1->prev; + elem2->next = elem1; + elem1->prev = elem2; + if (elem2->prev) { + elem2->prev->next = elem2; + } +} +/*******************************************/ + +/* + * elemX, elem1, elemY => elemX, elem2, elemY + */ +static void +REPLACE_ELEM(LINK_ELEMENT *elem1, LINK_ELEMENT *elem2) +{ + elem2->prev = elem1->prev; + elem2->next = elem1->next; + if (elem1->prev) { + elem1->prev->next = elem2; + } + if (elem1->next) { + elem1->next->prev = elem2; + } +} + +static void +REMOVE_ELEM(LINK_ELEMENT *elem) +{ + elem->prev->next = elem->next; + if (elem->next) { + elem->next->prev = elem->prev; + } +} + +static LINK_ELEMENT * +FIRST_ELEMENT(LINK_ANCHOR *anchor) +{ + return anchor->anchor.next; +} + +/* +static LINK_ELEMENT * +LAST_ELEMENT(LINK_ANCHOR *anchor) +{ + return anchor->last; +} + */ + +static LINK_ELEMENT * +POP_ELEMENT(LINK_ANCHOR *anchor) +{ + LINK_ELEMENT *elem = anchor->last; + anchor->last = anchor->last->prev; + anchor->last->next = 0; + verify_list("pop", anchor); + return elem; +} + +static LINK_ELEMENT * +SHIFT_ELEMENT(LINK_ANCHOR *anchor) +{ + LINK_ELEMENT *elem = anchor->anchor.next; + if (elem) { + anchor->anchor.next = elem->next; + } + return elem; +} + +static int +LIST_SIZE(LINK_ANCHOR *anchor) +{ + LINK_ELEMENT *elem = anchor->anchor.next; + int size = 0; + while (elem) { + size += 1; + elem = elem->next; + } + return size; +} + +static int +LIST_SIZE_ZERO(LINK_ANCHOR *anchor) +{ + if (anchor->anchor.next == 0) { + return 1; + } + else { + return 0; + } +} + +/* + * anc1: e1, e2, e3 + * anc2: e4, e5 + *#=> + * anc1: e1, e2, e3, e4, e5 + * anc2: e4, e5 (broken) + */ +static void +APPEND_LIST(LINK_ANCHOR *anc1, LINK_ANCHOR *anc2) +{ + if (anc2->anchor.next) { + anc1->last->next = anc2->anchor.next; + anc2->anchor.next->prev = anc1->last; + anc1->last = anc2->last; + } + verify_list("append", anc1); +} + +/* + * anc1: e1, e2, e3 + * anc2: e4, e5 + *#=> + * anc1: e4, e5, e1, e2, e3 + * anc2: e4, e5 (broken) + */ +static void +INSERT_LIST(LINK_ANCHOR *anc1, LINK_ANCHOR *anc2) +{ + if (anc2->anchor.next) { + LINK_ELEMENT *first = anc1->anchor.next; + anc1->anchor.next = anc2->anchor.next; + anc1->anchor.next->prev = &anc1->anchor; + anc2->last->next = first; + if (first) { + first->prev = anc2->last; + } + else { + anc1->last = anc2->last; + } + } + + 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; + + /* it has bug */ + *anc2 = *anc1; + *anc1 = tmp; + + verify_list("swap1", anc1); + verify_list("swap2", anc2); +} + +static LINK_ANCHOR * +REVERSE_LIST(LINK_ANCHOR *anc) +{ + LINK_ELEMENT *first, *last, *elem, *e; + first = &anc->anchor; + elem = first->next; + last = anc->last; + + if (elem != 0) { + anc->anchor.next = last; + anc->last = elem; + } + else { + /* null list */ + return anc; + } + while (elem) { + e = elem->next; + elem->next = elem->prev; + elem->prev = e; + elem = e; + } + + first->next = last; + last->prev = first; + anc->last->next = 0; + + verify_list("reverse", anc); + return anc; +} +#endif + +#if CPDEBUG > 0 +static void +debug_list(LINK_ANCHOR *anchor) +{ + LINK_ELEMENT *list = FIRST_ELEMENT(anchor); + printf("----\n"); + printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor, + anchor->anchor.next, anchor->last); + while (list) { + printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next, + list->prev, FIX2INT(list->type)); + list = list->next; + } + printf("----\n"); + + dump_disasm_list(anchor->anchor.next); + verify_list("debug list", anchor); +} +#endif + +static LABEL * +new_label_body(yarv_iseq_t *iseq, int line) +{ + LABEL *labelobj = compile_data_alloc_label(iseq); + static int label_no = 0; + + labelobj->link.type = ISEQ_ELEMENT_LABEL; + labelobj->link.next = 0; + + labelobj->label_no = label_no++; + labelobj->sc_state = 0; + labelobj->sp = -1; + return labelobj; +} + +static INSN * +new_insn_core(yarv_iseq_t *iseq, int line_no, + int insn_id, int argc, VALUE *argv) +{ + INSN *iobj = compile_data_alloc_insn(iseq); + + iobj->link.type = ISEQ_ELEMENT_INSN; + iobj->link.next = 0; + iobj->insn_id = insn_id; + iobj->line_no = line_no; + iobj->operands = argv; + iobj->operand_size = argc; + iobj->sc_state = 0; + return iobj; +} + +static INSN * +new_insn_body(yarv_iseq_t *iseq, int line_no, int insn_id, int argc, ...) +{ + VALUE *operands = 0; + va_list argv; + if (argc > 0) { + int i; + va_init_list(argv, argc); + operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc); + for (i = 0; i < argc; i++) { + VALUE v = va_arg(argv, VALUE); + operands[i] = v; + } + va_end(argv); + } + return new_insn_core(iseq, line_no, insn_id, argc, operands); +} + +static INSN * +new_insn_send(yarv_iseq_t *iseq, int line_no, + VALUE id, VALUE argc, VALUE block, VALUE flag) +{ + INSN *iobj = 0; + VALUE *operands = + (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 5); + operands[0] = id; + operands[1] = argc; + operands[2] = block; + operands[3] = flag; + operands[4] = 0; + iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands); + return iobj; +} + +static VALUE +new_child_iseq(yarv_iseq_t *iseq, NODE *node, + VALUE name, VALUE parent, VALUE type) +{ + VALUE args[6]; + VALUE ret; + + debugs("[new_child_iseq]> ---------------------------------------\n"); + ret = yarv_iseq_new_with_opt(node, name, iseq_filename(iseq->self), + parent, type, iseq->compile_data->option); + debugs("[new_child_iseq]< ---------------------------------------\n"); + iseq_add_mark_object(iseq, ret); + return ret; +} + +static int +iseq_setup(yarv_iseq_t *iseq, LINK_ANCHOR *anchor) +{ + // debugs("[compile step 2] (iseq_array_to_linkedlist)\n"); + + GC_CHECK(); + if (CPDEBUG > 5) + dump_disasm_list(FIRST_ELEMENT(anchor)); + GC_CHECK(); + + debugs("[compile step 3.1 (iseq_optimize)]\n"); + iseq_optimize(iseq, anchor); + + if (CPDEBUG > 5) + dump_disasm_list(FIRST_ELEMENT(anchor)); + GC_CHECK(); + + if (iseq->compile_data->option->instructions_unification) { + debugs("[compile step 3.2 (iseq_insns_unification)]\n"); + iseq_insns_unification(iseq, anchor); + if (CPDEBUG > 5) + dump_disasm_list(FIRST_ELEMENT(anchor)); + GC_CHECK(); + } + + if (iseq->compile_data->option->stack_caching) { + debugs("[compile step 3.3 (set_sequence_stackcaching)]\n"); + set_sequence_stackcaching(iseq, anchor); + if (CPDEBUG > 5) + dump_disasm_list(FIRST_ELEMENT(anchor)); + GC_CHECK(); + } + + debugs("[compile step 4.1 (set_sequence)]\n"); + set_sequence(iseq, anchor); + if (CPDEBUG > 5) + dump_disasm_list(FIRST_ELEMENT(anchor)); + GC_CHECK(); + + GC_CHECK(); + debugs("[compile step 4.2 (set_exception_table)]\n"); + set_exception_table(iseq); + + debugs("[compile step 4.3 (set_optargs_table)] \n"); + set_optargs_table(iseq); + + debugs("[compile step 5 (iseq_translate_direct_threaded_code)] \n"); + iseq_translate_direct_threaded_code(iseq); + GC_CHECK(); + + if (CPDEBUG > 1) { + VALUE str = iseq_disasm(iseq->self); + printf("%s\n", StringValueCStr(str)); + fflush(stdout); + } + debugs("[compile step: finish]\n"); + + return 0; +} + +VALUE +iseq_assemble_setup(VALUE self, VALUE args, VALUE locals, VALUE insn_ary) +{ + /* unsupported */ + return Qnil; +} + +int +set_exception_tbl(yarv_iseq_t *iseq) +{ + static ID id_dollar_bang; + + if (!id_dollar_bang) { + id_dollar_bang = rb_intern("#$!"); + } + iseq->local_tbl = (ID *)ALLOC_N(ID *, 1); + iseq->local_size = 1; + iseq->local_tbl[0] = id_dollar_bang; + return COMPILE_OK; +} + +static int +search_block_local_variables(NODE * node, VALUE local_vars) +{ + switch (nd_type(node)) { + case NODE_DASGN_CURR:{ + rb_ary_push(local_vars, ID2SYM(node->nd_vid)); + break; + } + case NODE_MASGN:{ + NODE *narg = node->nd_head; + while (narg) { + search_block_local_variables(narg->nd_head, local_vars); + narg = narg->nd_next; + } + if (node->nd_args != 0 && (long)node->nd_args != -1) { + search_block_local_variables(node->nd_args, local_vars); + break; + } + } + default: + break; + } + return COMPILE_OK; +} + +static NODE * +search_block_local_parameters(yarv_iseq_t *iseq, NODE * lnode) +{ + NODE *node = lnode; + NODE *nelem; + VALUE local_vars = rb_ary_new(); + VALUE param_vars = rb_ary_new(); + + /* search args */ + if (node->nd_var && (VALUE)node->nd_var != 1) { + switch (nd_type(node->nd_var)) { + case NODE_DASGN_CURR: + iseq->argc = 1; + rb_ary_push(param_vars, ID2SYM(node->nd_var->nd_vid)); + debugi("block 1arg", node->nd_var->nd_vid); + break; + case NODE_MASGN:{ + int i; + nelem = node->nd_var->nd_head; + if (nelem != 0) { + iseq->argc = node->nd_var->nd_head->nd_alen; + for (i = 0; i < iseq->argc; i++, nelem = nelem->nd_next) { + if (nd_type(nelem->nd_head) == NODE_DASGN_CURR) { + rb_ary_push(param_vars, + ID2SYM(nelem->nd_head->nd_vid)); + debugi("block arg", nelem->nd_head->nd_vid); + } + else { + char buff[0x20]; + ID id; + int idx = iseq->argc - RARRAY_LEN(param_vars); + snprintf(buff, 0x20, "#blp%d", idx); + id = rb_intern(buff); + rb_ary_push(param_vars, ID2SYM(id)); + debugi("block arg (auto)", id); + search_block_local_variables(nelem->nd_head, + local_vars); + } + } + } + if (node->nd_var->nd_args) { + NODE *sn = node->nd_var->nd_args; + if ((long)sn != -1) { + if (nd_type(sn) == NODE_DASGN_CURR) { + rb_ary_push(param_vars, ID2SYM(sn->nd_vid)); + } + else { + rb_ary_push(param_vars, + ID2SYM(rb_intern("#blp_splat"))); + debugi("block/splat (auto)", + rb_intern("#blp_splat")); + } + } + } + break; + } + default: + rb_ary_push(param_vars, ID2SYM(rb_intern("#blp"))); + debugi("block 1arg (auto)", rb_intern("#blp")); + iseq->argc = 1; + break; + } + } + else { + iseq->argc = 0; + } + + node = node->nd_body; + + /* other block local variables 2 */ + if (node && nd_type(node) == NODE_BLOCK) { + nelem = node->nd_head; + if (nelem && nd_type(nelem) == NODE_DASGN_CURR) { + while (nelem && nd_type(nelem) == NODE_DASGN_CURR) { + if (!rb_ary_includes(local_vars, ID2SYM(nelem->nd_vid))) { + debugi("block initialized variable", nelem->nd_vid); + rb_ary_push(local_vars, ID2SYM(nelem->nd_vid)); + } + nelem = nelem->nd_value; + } + if (nelem == 0) { + node = node->nd_next; + } + } + } + + /* translate to block inlining code */ + if (iseq->special_block_builder != 0) { + node = ((NODE * (*)(yarv_iseq_t *, NODE *, NODE *, VALUE, VALUE)) + iseq->special_block_builder) (iseq, node, lnode->nd_var, + param_vars, local_vars); + } + + rb_ary_concat(param_vars, local_vars); + local_vars = param_vars; + + { + int i, size = RARRAY_LEN(local_vars); + + if (size > 0) { + iseq->local_tbl = ALLOC_N(ID, size); + for (i = 0; i < size; i++) { + iseq->local_tbl[i] = SYM2ID(RARRAY_PTR(local_vars)[i]); + debugi("block local variable", iseq->local_tbl[i]); + } + } + iseq->local_size = size; + } + return node; +} + +static int +set_block_initializer(yarv_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor, int didx) +{ + DECL_ANCHOR(anc); + LINK_ELEMENT *elem; + + COMPILE_POPED(anc, "set_block_local_tbl#masgn/other", node); + + if (nd_type(node) == NODE_ATTRASGN) { + INSN *iobj = (INSN *)anc->last->prev; + iobj->operands[1] = INT2FIX(FIX2INT(iobj->operands[1]) + 1); + INSERT_ELEM_PREV((void *)iobj, + (void *)new_insn_body(iseq, nd_line(node), + BIN(getdynamic), 2, + INT2FIX(didx), INT2FIX(0))); + } + else { + ADD_INSN2(anchor, nd_line(node), getdynamic, + INT2FIX(didx), INT2FIX(0)); + elem = FIRST_ELEMENT(anc); + if (elem->type == ISEQ_ELEMENT_INSN && + ((INSN *)elem)->insn_id == BIN(putnil)) { + SHIFT_ELEMENT(anc); + } + } + APPEND_LIST(anchor, anc); + + return COMPILE_OK; +} + +static NODE * +set_block_local_tbl(yarv_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor) +{ + NODE *rnode; + + /* argument check */ + if (iseq->type != ISEQ_TYPE_BLOCK) { + rb_bug("set_block_local_tbl: unexpected iseq type"); + } + + rnode = search_block_local_parameters(iseq, node); + + if ((VALUE)node->nd_var == 1) { + /* TODO */ + } + else if (node->nd_var) { + NODE *nargs = node->nd_var; + switch (nd_type(nargs)) { + case NODE_MASGN:{ + NODE *massign = nargs; + int i = 0; + if (nargs->nd_head != 0) { + NODE *lhsn = massign->nd_head; + + while (lhsn) { + if (nd_type(lhsn->nd_head) != NODE_DASGN_CURR) { + /* idx-th param, current level */ + set_block_initializer(iseq, lhsn->nd_head, + anchor, iseq->local_size - i); + } + i++; + lhsn = lhsn->nd_next; + } + } + + /* check rest */ + if (massign->nd_args != 0 && (long)massign->nd_args != -1) { + iseq->argc++; + iseq->arg_rest = i + 1; + + if (nd_type(massign->nd_args) != NODE_DASGN_CURR) { + set_block_initializer(iseq, massign->nd_args, + anchor, iseq->local_size - i); + } + } + else if (i == 1) { + iseq->arg_rest = -1; + } + break; + } + + case NODE_DASGN_CURR: + break; + + /* for 1.x compatibility */ + default:{ + /* first param, current level */ + set_block_initializer(iseq, nargs, anchor, iseq->local_size); + break; + } + } + } + + if (iseq->arg_opts || iseq->arg_rest) { + iseq->arg_simple = 0; + } + else { + iseq->arg_simple = 1; + } + + if (nd_type(node) == NODE_FOR) { + iseq->compile_data->for_iseq = 1; + } + return rnode; +} + +static int +get_dyna_var_idx_at_raw(yarv_iseq_t *iseq, ID id) +{ + int i; + for (i = 0; i < iseq->local_size; i++) { + if (iseq->local_tbl[i] == id) { + return i; + } + } + return -1; +} + +static int +get_dyna_var_idx(yarv_iseq_t *iseq, ID id, int *level, int *ls) +{ + int lv = 0, idx; + + while (iseq) { + if ((idx = get_dyna_var_idx_at_raw(iseq, id)) >= 0) { + *level = lv; + *ls = iseq->local_size; + return idx; + } + iseq = iseq->parent_iseq; + lv++; + } + return -1; +} + +/** + + */ +static int +set_arguments(yarv_iseq_t *iseq, LINK_ANCHOR *optargs, NODE * node) +{ + int i, j; + + if (node) { + /* normal method */ + if (node->nd_frml) { + iseq->argc = RARRAY_LEN(node->nd_frml); + } + else { + iseq->argc = 0; + } + + if (node->nd_rest) { + iseq->arg_rest = node->nd_rest->nd_cnt - 2 + 1; + } + + /* optional initializer */ + if (node->nd_opt) { + NODE *optarg = node->nd_opt; + LABEL *label; + VALUE labels = rb_ary_new(); + i = 0; + while (optarg) { + label = NEW_LABEL(nd_line(node)); + rb_ary_push(labels, (VALUE)label | 1); + ADD_LABEL(optargs, label); + COMPILE_POPED(optargs, "optarg", optarg->nd_head); + + optarg = optarg->nd_next; + i += 1; + } + /* last label */ + label = NEW_LABEL(nd_line(node)); + rb_ary_push(labels, (VALUE)label | 1); + ADD_LABEL(optargs, label); + i += 1; + + iseq->arg_opts = i; + iseq->arg_opt_tbl = ALLOC_N(VALUE, i); + MEMCPY(iseq->arg_opt_tbl, RARRAY_PTR(labels), VALUE, i); + for (j = 0; j < i; j++) { + iseq->arg_opt_tbl[j] &= ~1; + } + } + else { + iseq->arg_opts = 0; + } + } + else { + iseq->argc = 0; + iseq->arg_rest = 0; + iseq->arg_opts = 0; + } + + if (iseq->arg_rest != 0 || iseq->arg_opts != 0) { + iseq->arg_simple = 0; + } + else { + iseq->arg_simple = 1; + } + return COMPILE_OK; +} + +static int +set_localtbl(yarv_iseq_t *iseq, ID *tbl) +{ + int size; + if (tbl) { + size = *tbl - 2 /* $~, $_ */ + 1 /* svar location */ ; + } + else { + size = 1; + } + iseq->local_tbl = (ID *)ALLOC_N(ID *, size); + if (tbl && size > 1) { + MEMCPY(iseq->local_tbl + 1, tbl + 3, ID *, size - 1); + } + iseq->local_size = size; + return COMPILE_OK; +} + +static int +set_localtbl_eval(yarv_iseq_t *iseq, ID *tbl) +{ + int size; + if (tbl) { + size = *tbl; + } + else { + size = 0; + } + if (tbl) { + iseq->local_tbl = (ID *)ALLOC_N(ID *, size); + MEMCPY(iseq->local_tbl, tbl + 1, ID *, size); + } + iseq->local_size = size; + return COMPILE_OK; +} + +/** + ruby insn object array -> raw instruction sequence + */ +static int +set_sequence(yarv_iseq_t *iseq, LINK_ANCHOR *anchor) +{ + LABEL *lobj; + INSN *iobj; + struct insn_info_struct *insn_info_tbl; + LINK_ELEMENT *list; + VALUE *generated_iseq; + + int k, pos, sp, stack_max = 0; + + GC_CHECK(); + + /* set label position */ + list = FIRST_ELEMENT(anchor); + k = pos = 0; + while (list) { + switch (list->type) { + case ISEQ_ELEMENT_INSN:{ + iobj = (INSN *)list; + pos += insn_data_length(iobj); + + k += 1; + break; + } + case ISEQ_ELEMENT_LABEL:{ + lobj = (LABEL *)list; + lobj->position = pos; + lobj->set = Qtrue; + break; + } + case ISEQ_ELEMENT_NONE:{ + /* ignore */ + break; + } + default: + dump_disasm_list(FIRST_ELEMENT(anchor)); + dump_disasm_list(list); + rb_bug("error: set_sequence"); + break; + } + list = list->next; + } + + /* make instruction sequence */ + generated_iseq = ALLOC_N(VALUE, pos); + insn_info_tbl = ALLOC_N(struct insn_info_struct, k); + + GC_CHECK(); + + list = FIRST_ELEMENT(anchor); + k = pos = sp = 0; + + while (list) { + switch (list->type) { + case ISEQ_ELEMENT_INSN:{ + int j, len, insn; + char *types; + VALUE *operands; + + iobj = (INSN *)list; + + if (iobj->insn_id == BIN(emptstack) && sp == 0) { + iobj->insn_id = BIN(nop); + } + 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); + + operands = iobj->operands; + insn = iobj->insn_id; + generated_iseq[pos] = insn; + types = insn_op_types(insn); + len = insn_len(insn); + + /* operand check */ + if (iobj->operand_size != len - 1) { + dump_disasm_list(list); + rb_bug("operand size miss! (%d for %d)", + iobj->operand_size, len - 1); + return 0; + } + + for (j = 0; types[j]; j++) { + char type = types[j]; + // printf("--> [%c - (%d-%d)]\n", type, k, j); + switch (type) { + case TS_OFFSET:{ + /* label(destination position) */ + lobj = (LABEL *)operands[j]; + if (lobj->set != Qtrue) { + rb_bug("unknown label"); + } + if (lobj->sp == -1) { + lobj->sp = sp; + } + generated_iseq[pos + 1 + j] = + lobj->position - (pos + len); + break; + } + case TS_CDHASH:{ + /* + * [obj, label, ...] + */ + int i; + VALUE lits = operands[j]; + VALUE map = rb_hash_new(); + + for (i=0; i < RARRAY_LEN(lits); i+=2) { + VALUE obj = rb_ary_entry(lits, i); + VALUE lv = rb_ary_entry(lits, i+1); + lobj = (LABEL *)(lv & ~1); + + if (lobj->set != Qtrue) { + rb_bug("unknown label"); + } + rb_hash_aset(map, obj, + INT2FIX(lobj->position - (pos+len))); + } + generated_iseq[pos + 1 + j] = map; + iseq_add_mark_object(iseq, map); + break; + } + case TS_LINDEX: + case TS_DINDEX: + case TS_NUM: /* ulong */ + generated_iseq[pos + 1 + j] = FIX2INT(operands[j]); + break; + case TS_ISEQ: /* iseq */ + { + VALUE v = operands[j]; + yarv_iseq_t *block = 0; + if (v) { + GetISeqPtr(v, block); + } + generated_iseq[pos + 1 + j] = (VALUE)block; + break; + } + case TS_VALUE: /* VALUE */ + { + VALUE v = operands[j]; + generated_iseq[pos + 1 + j] = v; + /* to mark ruby object */ + if (!SPECIAL_CONST_P(v)) { + iseq_add_mark_object(iseq, v); + } + break; + } + case TS_IC: /* inline cache */ + { + VALUE v = (VALUE)NEW_INLINE_CACHE_ENTRY(); + generated_iseq[pos + 1 + j] = v; + iseq_add_mark_object(iseq, v); + break; + } + case TS_ID: /* ID */ + generated_iseq[pos + 1 + j] = SYM2ID(operands[j]); + break; + case TS_GENTRY: + { + struct global_entry *entry = + (struct global_entry *)(operands[j] & (~1)); + generated_iseq[pos + 1 + j] = (VALUE)entry; + } + break; + default: + rb_bug("unknown operand type: %c", type); + return 0; + } + } + insn_info_tbl[k].line_no = iobj->line_no; + insn_info_tbl[k].position = pos; + pos += len; + k++; + break; + } + case ISEQ_ELEMENT_LABEL:{ + lobj = (LABEL *)list; + if (lobj->sp == -1) { + lobj->sp = sp; + } + else { + sp = lobj->sp; + } + break; + } + default: + /* ignore */ + break; + } + list = list->next; + } + + { + iseq->iseq = (void *)generated_iseq; + iseq->size = pos; + iseq->insn_info_tbl = insn_info_tbl; + iseq->insn_info_size = k; + iseq->stack_max = stack_max; + } + return COMPILE_OK; +} + +static int +label_get_position(LABEL *lobj) +{ + return lobj->position; +} + +static int +label_get_sp(LABEL *lobj) +{ + return lobj->sp; +} + +static int +set_exception_table(yarv_iseq_t *iseq) +{ + VALUE *tptr, *ptr; + int tlen, i; + struct catch_table_entry *entry; + + tlen = RARRAY_LEN(iseq->compile_data->catch_table_ary); + tptr = RARRAY_PTR(iseq->compile_data->catch_table_ary); + + iseq->catch_table = ALLOC_N(struct catch_table_entry, tlen); + iseq->catch_table_size = tlen; + + for (i = 0; i < tlen; i++) { + ptr = RARRAY_PTR(tptr[i]); + entry = &iseq->catch_table[i]; + entry->type = ptr[0] & 0xffff; + entry->start = label_get_position((LABEL *)(ptr[1] & ~1)); + entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); + entry->iseq = ptr[3]; + + /* register iseq as mark object */ + if (entry->iseq != 0) { + iseq_add_mark_object(iseq, entry->iseq); + } + + /* stack depth */ + if (ptr[4]) { + LABEL *lobj = (LABEL *)(ptr[4] & ~1); + entry->cont = label_get_position(lobj); + entry->sp = label_get_sp(lobj); + + /* TODO: Dirty Hack! Fix me */ + if (entry->type == CATCH_TYPE_RESCUE || + entry->type == CATCH_TYPE_BREAK || + (((ptr[0] & 0x10000) == 0) + && entry->type == CATCH_TYPE_NEXT)) { + entry->sp--; + } + } + else { + entry->cont = 0; + } + } + // + iseq->compile_data->catch_table_ary = 0; /* free */ + return COMPILE_OK; +} + +/* + * set optional argument table + * def foo(a, b=expr1, c=expr2) + * => + * b: + * expr1 + * c: + * expr2 + */ +static int +set_optargs_table(yarv_iseq_t *iseq) +{ + int i; + + if (iseq->arg_opts != 0) { + for (i = 0; i < iseq->arg_opts; i++) { + iseq->arg_opt_tbl[i] = + label_get_position((LABEL *)iseq->arg_opt_tbl[i]); + } + } + return COMPILE_OK; +} + +static LINK_ELEMENT * +get_destination_insn(INSN *iobj) +{ + LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0); + LINK_ELEMENT *list; + + list = lobj->link.next; + while (list) { + if (list->type == ISEQ_ELEMENT_INSN) { + break; + } + list = list->next; + } + return list; +} + +static LINK_ELEMENT * +get_next_insn(INSN *iobj) +{ + LINK_ELEMENT *list = iobj->link.next; + + while (list) { + if (list->type == ISEQ_ELEMENT_INSN) { + return list; + } + list = list->next; + } + return 0; +} + +static LINK_ELEMENT * +get_prev_insn(INSN *iobj) +{ + LINK_ELEMENT *list = iobj->link.prev; + + while (list) { + if (list->type == ISEQ_ELEMENT_INSN) { + return list; + } + list = list->prev; + } + return 0; +} + +static int +iseq_peephole_optimize(yarv_iseq_t *iseq, LINK_ELEMENT *list) +{ + INSN *iobj = (INSN *)list; + again: + if (iobj->insn_id == BIN(jump)) { + INSN *niobj, *diobj, *piobj; + /* + * useless jump elimination: + * jump LABEL1 + * ... + * LABEL1: + * jump LABEL2 + * + * => in this case, first jump instruction should jump tp + * LABEL2 directly + */ + diobj = (INSN *)get_destination_insn(iobj); + niobj = (INSN *)get_next_insn(iobj); + + if (diobj == niobj) { + REMOVE_ELEM(&iobj->link); + } + else if (iobj != diobj && diobj->insn_id == BIN(jump)) { + OPERAND_AT(iobj, 0) = OPERAND_AT(diobj, 0); + goto again; + } + else if (diobj->insn_id == BIN(leave)) { + INSN *eiobj = new_insn_core(iseq, iobj->line_no, BIN(leave), + diobj->operand_size, + diobj->operands); + /* replace */ + REPLACE_ELEM((LINK_ELEMENT *)iobj, (LINK_ELEMENT *)eiobj); + } + /* + * useless jump elimination (if/unless destination): + * if L1 + * jump L2 + * L1: + * ... + * L2: + * + * ==> + * unless L2 + * L1: + * ... + * L2: + */ + else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 && + (piobj->insn_id == BIN(branchif) || + piobj->insn_id == BIN(branchunless))) { + if (niobj == (INSN *)get_destination_insn(piobj)) { + piobj->insn_id = (piobj->insn_id == BIN(branchif)) + ? BIN(branchunless) : BIN(branchif) ; + OPERAND_AT(piobj, 0) = OPERAND_AT(iobj, 0); + REMOVE_ELEM(&iobj->link); + } + } + } + if (iobj->insn_id == BIN(branchif) || + iobj->insn_id == BIN(branchunless)) { + /* + * if L1 + * ... + * L1: + * jump L2 + * => + * if L2 + */ + INSN *nobj = (INSN *)get_destination_insn(iobj); + if (nobj->insn_id == BIN(jump)) { + OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0); + } + } + + if (iobj->insn_id == BIN(leave)) { + 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); + } + } + } + return COMPILE_OK; +} + +static int +insn_set_specialized_instruction(INSN *iobj, int insn_id) +{ + iobj->insn_id = insn_id; + iobj->operand_size = 0; + return COMPILE_OK; +} + + +static int +iseq_specialized_instruction(yarv_iseq_t *iseq, INSN *iobj) +{ + if (iobj->insn_id == BIN(send)) { + ID mid = SYM2ID(OPERAND_AT(iobj, 0)); + int argc = FIX2INT(OPERAND_AT(iobj, 1)); + VALUE block = OPERAND_AT(iobj, 2); + VALUE flag = OPERAND_AT(iobj, 3); + + /* TODO: should be more sophisticated search */ + if (block == 0 && flag == INT2FIX(0)) { + if (argc == 0) { + if (mid == idLength) { + insn_set_specialized_instruction(iobj, BIN(opt_length)); + } + else if (mid == idSucc) { + insn_set_specialized_instruction(iobj, BIN(opt_succ)); + } + } + else if (argc == 1) { + if (0) { + } + else if (mid == idPLUS) { + insn_set_specialized_instruction(iobj, BIN(opt_plus)); + } + else if (mid == idMINUS) { + insn_set_specialized_instruction(iobj, BIN(opt_minus)); + } + else if (mid == idMULT) { + insn_set_specialized_instruction(iobj, BIN(opt_mult)); + } + else if (mid == idDIV) { + insn_set_specialized_instruction(iobj, BIN(opt_div)); + } + else if (mid == idMOD) { + insn_set_specialized_instruction(iobj, BIN(opt_mod)); + } + else if (mid == idEq) { + insn_set_specialized_instruction(iobj, BIN(opt_eq)); + } + else if (mid == idLT) { + insn_set_specialized_instruction(iobj, BIN(opt_lt)); + } + else if (mid == idLE) { + insn_set_specialized_instruction(iobj, BIN(opt_le)); + } + else if (mid == idLTLT) { + insn_set_specialized_instruction(iobj, BIN(opt_ltlt)); + } + else if (mid == idAREF) { + insn_set_specialized_instruction(iobj, BIN(opt_aref)); + } + } + } + } + return COMPILE_OK; +} + +static int +iseq_optimize(yarv_iseq_t *iseq, LINK_ANCHOR *anchor) +{ + LINK_ELEMENT *list; + const int do_peephole = iseq->compile_data->option->peephole_optimization; + const int do_si = iseq->compile_data->option->specialized_instruction; + const int do_ou = iseq->compile_data->option->operands_unification; + list = FIRST_ELEMENT(anchor); + + while (list) { + if (list->type == ISEQ_ELEMENT_INSN) { + if (do_peephole) { + iseq_peephole_optimize(iseq, list); + } + if (do_si) { + iseq_specialized_instruction(iseq, (INSN *)list); + } + if (do_ou) { + insn_operands_unification((INSN *)list); + } + } + list = list->next; + } + return COMPILE_OK; +} + +#if OPT_INSTRUCTIONS_UNIFICATION +static INSN * +new_unified_insn(yarv_iseq_t *iseq, + int insn_id, int size, LINK_ELEMENT *seq_list) +{ + INSN *iobj = 0; + LINK_ELEMENT *list = seq_list; + int i, argc = 0; + VALUE *operands = 0, *ptr = 0; + + + /* count argc */ + for (i = 0; i < size; i++) { + iobj = (INSN *)list; + argc += iobj->operand_size; + list = list->next; + } + + if (argc > 0) { + ptr = operands = + (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc); + } + + /* copy operands */ + list = seq_list; + for (i = 0; i < size; i++) { + iobj = (INSN *)list; + MEMCPY(ptr, iobj->operands, VALUE, iobj->operand_size); + ptr += iobj->operand_size; + list = list->next; + } + + return new_insn_core(iseq, iobj->line_no, insn_id, argc, operands); +} +#endif + +/* + * This scheme can get more performance if do this optimize with + * label address resolving. + * It's future work (if compile time was bottle neck). + */ +static int +iseq_insns_unification(yarv_iseq_t *iseq, LINK_ANCHOR *anchor) +{ +#if OPT_INSTRUCTIONS_UNIFICATION + LINK_ELEMENT *list; + INSN *iobj, *niobj; + int id, j, k; + + list = FIRST_ELEMENT(anchor); + while (list) { + if (list->type == ISEQ_ELEMENT_INSN) { + iobj = (INSN *)list; + id = iobj->insn_id; + if (unified_insns_data[id] != 0) { + int **entry = unified_insns_data[id]; + for (j = 1; j < (int)entry[0]; j++) { + int *unified = entry[j]; + LINK_ELEMENT *li = list->next; + for (k = 2; k < unified[1]; k++) { + if (li->type != ISEQ_ELEMENT_INSN || + ((INSN *)li)->insn_id != unified[k]) { + goto miss; + } + li = li->next; + } + /* matched */ + niobj = + new_unified_insn(iseq, unified[0], unified[1] - 1, + list); + + /* insert to list */ + niobj->link.prev = (LINK_ELEMENT *)iobj->link.prev; + niobj->link.next = li; + if (li) { + li->prev = (LINK_ELEMENT *)niobj; + } + + list->prev->next = (LINK_ELEMENT *)niobj; + list = (LINK_ELEMENT *)niobj; + break; + miss:; + } + } + } + list = list->next; + } +#endif + return COMPILE_OK; +} + +#if OPT_STACK_CACHING + +#define SC_INSN(insn, stat) sc_insn_info[(insn)][(stat)] +#define SC_NEXT(insn) sc_insn_next[insn] + +#include "opt_sc.inc" + +static int +insn_set_sc_state(INSN *iobj, int state) +{ + int nstate; + int insn_id; + + insn_id = iobj->insn_id; + iobj->insn_id = SC_INSN(insn_id, state); + nstate = SC_NEXT(iobj->insn_id); + + if (insn_id == BIN(jump) || + insn_id == BIN(branchif) || insn_id == BIN(branchunless)) { + LABEL *lobj = (LABEL *)OPERAND_AT(iobj, 0); + + if (lobj->sc_state != 0) { + if (lobj->sc_state != nstate) { + dump_disasm_list((LINK_ELEMENT *)iobj); + dump_disasm_list((LINK_ELEMENT *)lobj); + printf("\n-- %d, %d\n", lobj->sc_state, nstate); + rb_bug("insn_set_sc_state error\n"); + return 0; + } + } + else { + lobj->sc_state = nstate; + } + if (insn_id == BIN(jump)) { + nstate = SCS_XX; + } + } + else if (insn_id == BIN(leave)) { + nstate = SCS_XX; + } + + return nstate; +} + +static int +label_set_sc_state(LABEL *lobj, int state) +{ + if (lobj->sc_state != 0) { + if (lobj->sc_state != state) { + state = lobj->sc_state; + } + } + else { + lobj->sc_state = state; + } + + return state; +} + + +#endif + +static int +set_sequence_stackcaching(yarv_iseq_t *iseq, LINK_ANCHOR *anchor) +{ +#if OPT_STACK_CACHING + LINK_ELEMENT *list; + int state, insn_id; + + /* initialize */ + state = SCS_XX; + list = FIRST_ELEMENT(anchor); + // dump_disasm_list(list); + + /* for each list element */ + while (list) { + redo_point: + switch (list->type) { + case ISEQ_ELEMENT_INSN:{ + INSN *iobj = (INSN *)list; + insn_id = iobj->insn_id; + + // dump_disasm_list(list); + + switch (insn_id) { + case BIN(nop):{ + /* exception merge point */ + if (state != SCS_AX) { + INSN *rpobj = + new_insn_body(iseq, 0, BIN(reput), 0); + + /* replace this insn */ + REPLACE_ELEM(list, (LINK_ELEMENT *)rpobj); + list = (LINK_ELEMENT *)rpobj; + goto redo_point; + } + break; + } + case BIN(swap):{ + if (state == SCS_AB || state == SCS_BA) { + state = (state == SCS_AB ? SCS_BA : SCS_AB); + + REMOVE_ELEM(list); + list = list->next; + goto redo_point; + } + break; + } + case BIN(pop):{ + switch (state) { + case SCS_AX: + case SCS_BX: + state = SCS_XX; + break; + case SCS_AB: + state = SCS_AX; + break; + case SCS_BA: + state = SCS_BX; + break; + case SCS_XX: + goto normal_insn; + default: + rb_bug("unreachable"); + } + /* remove useless pop */ + REMOVE_ELEM(list); + list = list->next; + goto redo_point; + } + default:; + /* none */ + } /* end of switch */ + normal_insn: + state = insn_set_sc_state(iobj, state); + break; + } + case ISEQ_ELEMENT_LABEL:{ + LABEL *lobj; + lobj = (LABEL *)list; + + state = label_set_sc_state(lobj, state); + } + default: + break; + } + list = list->next; + } +#endif + return COMPILE_OK; +} + + + +static int +compile_dstr(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node) +{ + NODE *list = node->nd_next; + VALUE lit = node->nd_lit; + int cnt = 1; + + debugp_param("nd_lit", lit); + ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); + + while (list) { + COMPILE(ret, "each string", list->nd_head); + cnt++; + list = list->nd_next; + } + + ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt)); + return COMPILE_OK; +} + +static int +compile_branch_condition(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond, + LABEL *then_label, LABEL *else_label) +{ + switch (nd_type(cond)) { + case NODE_NOT: + compile_branch_condition(iseq, ret, cond->nd_body, else_label, + then_label); + break; + + case NODE_AND:{ + LABEL *label = NEW_LABEL(nd_line(cond)); + compile_branch_condition(iseq, ret, cond->nd_1st, label, + else_label); + ADD_LABEL(ret, label); + compile_branch_condition(iseq, ret, cond->nd_2nd, then_label, + else_label); + break; + } + case NODE_OR:{ + LABEL *label = NEW_LABEL(nd_line(cond)); + compile_branch_condition(iseq, ret, cond->nd_1st, then_label, + label); + ADD_LABEL(ret, label); + compile_branch_condition(iseq, ret, cond->nd_2nd, then_label, + else_label); + break; + } + case NODE_LIT: /* NODE_LIT is always not true */ + case NODE_TRUE: + case NODE_STR: + /* printf("useless conditon eliminate (%s)\n", node_name(nd_type(cond))); */ + ADD_INSNL(ret, nd_line(cond), jump, then_label); + break; + case NODE_FALSE: + case NODE_NIL: + /* printf("useless conditon eliminate (%s)\n", node_name(nd_type(cond))); */ + ADD_INSNL(ret, nd_line(cond), jump, else_label); + break; + default: + COMPILE(ret, "branch condition", cond); + ADD_INSNL(ret, nd_line(cond), branchunless, else_label); + ADD_INSNL(ret, nd_line(cond), jump, then_label); + break; + } + return COMPILE_OK; +} + +static int +compile_array(yarv_iseq_t *iseq, + LINK_ANCHOR *ret, NODE * node_root, VALUE opt_p) +{ + NODE *node = node_root; + int len = node->nd_alen, line = nd_line(node), i=0; + DECL_ANCHOR(anchor); + + while (node) { + i++; + if (opt_p && nd_type(node->nd_head) != NODE_LIT) { + opt_p = Qfalse; + } + COMPILE(anchor, "array element", node->nd_head); + node = node->nd_next; + } + + if (len != i) { + if (0) rb_bug("node error: compile_array (%d: %d-%d)", + nd_line(node_root), len, i); + len = i; + } + + if (opt_p == Qtrue) { + VALUE ary = rb_ary_new(); + node = node_root; + while (node) { + rb_ary_push(ary, node->nd_head->nd_lit); + node = node->nd_next; + } + + iseq_add_mark_object_compile_time(iseq, ary); + ADD_INSN1(ret, nd_line(node_root), duparray, ary); + } + else { + ADD_INSN1(anchor, line, newarray, INT2FIX(len)); + APPEND_LIST(ret, anchor); + } + return len; +} + +static VALUE +case_when_optimizable_literal(NODE * node) +{ + if (nd_type(node) == NODE_LIT) { + VALUE v = node->nd_lit; + VALUE klass = CLASS_OF(v); + if (klass == rb_cSymbol || rb_obj_is_kind_of(v, rb_cNumeric)) { + return v; + } + } + else if (nd_type(node) == NODE_STR) { + return node->nd_lit; + } + return Qfalse; +} + +static VALUE +when_vals(yarv_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, VALUE special_literals) +{ + while (vals) { + VALUE lit; + NODE* val; + + val = vals->nd_head; + + if (special_literals && + (lit = case_when_optimizable_literal(val)) != Qfalse) { + rb_ary_push(special_literals, lit); + rb_ary_push(special_literals, (VALUE)(l1) | 1); + } + else { + special_literals = Qfalse; + } + + COMPILE(cond_seq, "when cond", val); + ADD_INSN1(cond_seq, nd_line(val), topn, INT2FIX(1)); + ADD_SEND(cond_seq, nd_line(val), ID2SYM(idEqq), INT2FIX(1)); + ADD_INSNL(cond_seq, nd_line(val), branchif, l1); + vals = vals->nd_next; + } + return special_literals; +} + +static int +make_masgn_lhs(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node) +{ + + switch (nd_type(node)) { + case NODE_ATTRASGN:{ + INSN *iobj; + VALUE dupidx; + + COMPILE_POPED(ret, "masgn lhs (NODE_ATTRASGN)", node); + POP_ELEMENT(ret); /* pop pop insn */ + iobj = (INSN *)POP_ELEMENT(ret); /* pop send insn */ + + dupidx = iobj->operands[1]; + dupidx = INT2FIX(FIX2INT(dupidx) + 1); + iobj->operands[1] = dupidx; + + ADD_INSN1(ret, nd_line(node), topn, dupidx); + ADD_ELEM(ret, (LINK_ELEMENT *)iobj); + ADD_INSN(ret, nd_line(node), pop); /* result */ + ADD_INSN(ret, nd_line(node), pop); /* rhs */ + break; + } + + case NODE_MASGN: + COMPILE_POPED(ret, "nest masgn lhs", node); + break; + + default:{ + DECL_ANCHOR(anchor); + COMPILE_POPED(anchor, "masgn lhs", node); + // dump_disasm_list(FIRST_ELEMENT(anchor)); + REMOVE_ELEM(FIRST_ELEMENT(anchor)); + // dump_disasm_list(FIRST_ELEMENT(anchor)); + ADD_SEQ(ret, anchor); + // ADD_ELEM(ret, LAST_ELEMENT(anchor)); + } + } + + return COMPILE_OK; +} + +static int +compile_massign(yarv_iseq_t *iseq, LINK_ANCHOR *ret, + NODE * rhsn, NODE * splatn, NODE * lhsn, int llen) +{ + if (lhsn != 0) { + compile_massign(iseq, ret, rhsn, splatn, lhsn->nd_next, llen + 1); + make_masgn_lhs(iseq, ret, lhsn->nd_head); + } + else { + int lhs_splat = 0; + + if (splatn && (VALUE)splatn != -1) { + lhs_splat = 1; + } + + if (rhsn) { + switch (nd_type(rhsn)) { + case NODE_ARRAY:{ + int rlen = rhsn->nd_alen; + int max = rlen > llen ? rlen : llen; + int i, si = 0; + + for (i = 0; i < max; i++) { + if (i < rlen && i < llen) { + /* a, b = c, d */ + COMPILE(ret, "masgn val1", rhsn->nd_head); + rhsn = rhsn->nd_next; + } + else if (i < rlen) { + if (lhs_splat) { + while (rhsn) { + /* a, *b = x, y, z */ + si++; + COMPILE(ret, "masgn rhs for lhs splat", + rhsn->nd_head); + rhsn = rhsn->nd_next; + } + break; + } + else { + /* a, b = c, d, e */ + COMPILE_POPED(ret, "masgn rhs (popped)", + rhsn->nd_head); + rhsn = rhsn->nd_next; + } + } + else if (i < llen) { + /* a, b, c = c, d */ + ADD_INSN(ret, 0, putnil); + } + } + + if (lhs_splat) { + ADD_INSN1(ret, 0, newarray, INT2FIX(si)); + } + break; + } + case NODE_TO_ARY: + COMPILE(ret, "rhs to ary", rhsn->nd_head); + ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), + INT2FIX(lhs_splat)); + break; + + case NODE_SPLAT: + COMPILE(ret, "rhs to ary (splat)", rhsn->nd_head); + ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), + INT2FIX(lhs_splat)); + break; + + case NODE_ARGSCAT:{ + NODE *ary = rhsn->nd_head; + int idx = 0; + + while (ary) { + if (idx < llen || lhs_splat) { + COMPILE(ret, "rhs aggscat each head", + ary->nd_head); + } + else { + COMPILE_POPED(ret, + "rhs aggscat each head (popped)", + ary->nd_head); + } + ary = ary->nd_next; + idx++; + } + + if (llen > idx) { + COMPILE(ret, "rhs to ary (argscat/splat)", + rhsn->nd_body); + ADD_INSN2(ret, nd_line(rhsn), expandarray, + INT2FIX(llen - idx), INT2FIX(lhs_splat)); + } + else if (lhs_splat) { + COMPILE(ret, "rhs to ary (argscat/splat)", + rhsn->nd_body); + ADD_INSN2(ret, nd_line(rhsn), expandarray, + INT2FIX(llen - idx), INT2FIX(lhs_splat)); + } + break; + } + default: + COMPILE(ret, "rhs to ary (splat/default)", rhsn); + ADD_INSN2(ret, nd_line(rhsn), expandarray, INT2FIX(llen), + INT2FIX(lhs_splat)); + // rb_bug("unknown rhs: %s", node_name(nd_type(rhsn))); + } + } + else { + /* nested massign */ + ADD_INSN2(ret, 0, expandarray, INT2FIX(llen), INT2FIX(lhs_splat)); + } + + if (lhs_splat) { + make_masgn_lhs(iseq, ret, splatn); + } + } + return COMPILE_OK; +} + +static int +compile_colon2(yarv_iseq_t *iseq, NODE * node, + LINK_ANCHOR *pref, LINK_ANCHOR *body) +{ + switch (nd_type(node)) { + case NODE_CONST: + debugi("compile_colon2 - colon", node->nd_vid); + ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid)); + break; + case NODE_COLON3: + debugi("compile_colon2 - colon3", node->nd_mid); + ADD_INSN(body, nd_line(node), pop); + ADD_INSN1(body, nd_line(node), putobject, rb_cObject); + ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); + break; + case NODE_COLON2: + compile_colon2(iseq, node->nd_head, pref, body); + debugi("compile_colon2 - colon2", node->nd_mid); + ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid)); + break; + default: + COMPILE(pref, "const colon2 prefix", node); + break; + } + return COMPILE_OK; +} + +static int +compile_cpath(LINK_ANCHOR *ret, yarv_iseq_t *iseq, NODE *cpath) +{ + if(cpath->nd_head) { + COMPILE(ret, "nd_else->nd_head", cpath->nd_head); + } + else if (nd_type(cpath) == NODE_COLON2) { + COMPILE(ret, "cpath (NODE_COLON2)", cpath->nd_head); + } + else { + ADD_INSN1(ret, nd_line(cpath), putobject, rb_cObject); + } + return COMPILE_OK; +} + +static int +defined_expr(yarv_iseq_t *iseq, LINK_ANCHOR *ret, + NODE * node, LABEL *lfinish, VALUE needstr) +{ + char *estr = 0; + + switch (nd_type(node)) { + + /* easy literals */ + case NODE_NIL: + estr = "nil"; + break; + case NODE_SELF: + estr = "self"; + break; + case NODE_TRUE: + estr = "true"; + break; + case NODE_FALSE: + estr = "false"; + break; + case NODE_STR: + case NODE_LIT: + estr = "expression"; + break; + + /* variables */ + case NODE_LVAR: + estr = "local-variable"; + break; + case NODE_DVAR: + estr = "local-variable(in-block)"; + break; + + case NODE_IVAR: + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_IVAR), + ID2SYM(node->nd_vid), needstr); + return 1; + + case NODE_GVAR: + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_GVAR), + ((VALUE)node->nd_entry) | 1, needstr); + return 1; + + case NODE_CVAR: + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CVAR), + ID2SYM(node->nd_vid), needstr); + return 1; + + case NODE_CONST: + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST), + ID2SYM(node->nd_vid), needstr); + return 1; + case NODE_COLON2: + if (rb_is_const_id(node->nd_mid)) { + LABEL *lcont = NEW_LABEL(nd_line(node)); + defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse); + + ADD_INSNL(ret, nd_line(node), branchif, lcont) ; + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSNL(ret, nd_line(node), jump, lfinish); + + ADD_LABEL(ret, lcont); + COMPILE(ret, "defined/colon2#nd_head", node->nd_head); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST), + ID2SYM(node->nd_mid), needstr); + } + else { + LABEL *lcont = NEW_LABEL(nd_line(node)); + defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse); + + ADD_INSNL(ret, nd_line(node), branchif, lcont) ; + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSNL(ret, nd_line(node), jump, lfinish); + + ADD_LABEL(ret, lcont); + COMPILE(ret, "defined/colon2#nd_head", node->nd_head); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD), + ID2SYM(node->nd_mid), needstr); + } + return 1; + case NODE_COLON3: + ADD_INSN1(ret, nd_line(node), putobject, rb_cObject); + ADD_INSN3(ret, nd_line(node), defined, + INT2FIX(DEFINED_CONST), ID2SYM(node->nd_mid), needstr); + return 1; + + /* method dispatch */ + case NODE_CALL: + case NODE_VCALL: + case NODE_FCALL: + if (nd_type(node) == NODE_CALL) { + LABEL *lcont = NEW_LABEL(nd_line(node)); + + defined_expr(iseq, ret, node->nd_recv, lfinish, Qfalse); + ADD_INSNL(ret, nd_line(node), branchif, lcont) ; + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSNL(ret, nd_line(node), jump, lfinish); + + ADD_LABEL(ret, lcont); + COMPILE(ret, "defined/recv", node->nd_recv); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD), + ID2SYM(node->nd_mid), needstr); + } + else { + ADD_INSN(ret, nd_line(node), putself); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_FUNC), + ID2SYM(node->nd_mid), needstr); + } + return 1; + + case NODE_YIELD: + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_YIELD), 0, + needstr); + return 1; + + case NODE_NTH_REF: + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_REF), + INT2FIX(node->nd_nth), needstr); + return 1; + + case NODE_ZSUPER: + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_ZSUPER), 0, + needstr); + return 1; + + default:{ + LABEL *lstart = NEW_LABEL(nd_line(node)); + LABEL *lend = NEW_LABEL(nd_line(node)); + LABEL *ldefed = NEW_LABEL(nd_line(node)); + VALUE str = rb_str_new2("expression"); + VALUE tmp; + VALUE ensure = NEW_CHILD_ISEQVAL(NEW_NIL(), + rb_str_concat(rb_str_new2 + ("defined guard in "), + iseq->name), + ISEQ_TYPE_DEFINED_GUARD); + + iseq_add_mark_object_compile_time(iseq, str); + + ADD_LABEL(ret, lstart); + COMPILE(ret, "defined expr (others)", node); + ADD_INSNL(ret, nd_line(node), branchif, ldefed) ; + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSNL(ret, nd_line(node), jump, lend); + ADD_LABEL(ret, ldefed); + ADD_INSN1(ret, nd_line(node), putobject, str); + ADD_LABEL(ret, lend); + + ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, lstart, lend, ensure, lfinish); + return 1; + // rb_bug("unimplemented defined: %s", node_name(nd_type(node))); + } /* end of default */ + } + + if (estr != 0) { + if (needstr != Qfalse) { + VALUE str = rb_str_new2(estr); + ADD_INSN1(ret, nd_line(node), putstring, str); + iseq_add_mark_object_compile_time(iseq, str); + } + else { + ADD_INSN1(ret, nd_line(node), putobject, Qtrue); + } + return 1; + } + return 0; +} + +#define BUFSIZE 0x100 + +static VALUE +make_name_for_block(yarv_iseq_t *iseq) +{ + char buf[BUFSIZE]; + if (iseq->parent_iseq == 0) { + snprintf(buf, BUFSIZE, "block in %s", RSTRING_PTR(iseq->name)); + } + else { + int level = 1; + yarv_iseq_t *ip = iseq; + while (1) { + if (ip->local_iseq != ip) { + ip = ip->parent_iseq; + } + else { + break; + } + level++; + } + snprintf(buf, BUFSIZE, "block (%d levels) in %s", level, + RSTRING_PTR(ip->name)); + } + return rb_str_new2(buf); +} + +static VALUE +make_name_with_str(const char *fmt, const char *str) +{ + char buf[BUFSIZE]; + snprintf(buf, BUFSIZE, fmt, str); + 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) +{ + 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); + 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); +} + +static VALUE +setup_arg(yarv_iseq_t *iseq, LINK_ANCHOR *args, NODE *node, VALUE *flag) +{ + VALUE argc = INT2FIX(0); + NODE *argn = node->nd_args; + NODE *argp = 0; + DECL_ANCHOR(arg_block); + DECL_ANCHOR(args_push); + + if (argn && nd_type(argn) == NODE_BLOCK_PASS) { + COMPILE(arg_block, "block", argn->nd_body); + *flag |= VM_CALL_ARGS_BLOCKARG_BIT; + argn = argn->nd_head; + } + + setup_argn: + if (argn) { + switch (nd_type(argn)) { + case NODE_SPLAT: { + COMPILE(args, "args (splat)", argn->nd_head); + argc = INT2FIX(1); + *flag |= VM_CALL_ARGS_SPLAT_BIT; + break; + } + case NODE_ARGSCAT: { + argc = INT2FIX(compile_array(iseq, args, argn->nd_head, Qfalse) + 1); + POP_ELEMENT(args); + COMPILE(args, "args (cat: splat)", argn->nd_body); + *flag |= VM_CALL_ARGS_SPLAT_BIT; + break; + } + case NODE_ARGSPUSH: { + DECL_ANCHOR(args_push_e); + COMPILE(args_push_e, "argspush (cdr)", argn->nd_body); + ADD_INSN(args_push_e, nd_line(node), concatarray); + INSERT_LIST(args_push, args_push_e); + argn = argn->nd_head; + goto setup_argn; + } + default: { + argc = INT2FIX(compile_array(iseq, args, argn, Qfalse)); + POP_ELEMENT(args); + break; + } + } + } + + if (!LIST_SIZE_ZERO(args_push)) { + ADD_SEQ(args, args_push); + } + + if (*flag & VM_CALL_ARGS_BLOCKARG_BIT) { + ADD_SEQ(args, arg_block); + } + return argc; +} + + +/** + compile each node + + self: InstructionSequence + node: Ruby compiled node + poped: This node will be poped + */ +static int +iseq_compile_each(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) +{ + VALUE tmp; /* reserved for macro */ + int type; + + GC_CHECK(); + + if (node == 0) { + if (!poped) { + debug_nodeprint("NODE_NIL(implicit)"); + debug_nodeprint_close(); + ADD_INSN(ret, 0, putnil); + return COMPILE_OK; + } + return COMPILE_OK; + } + + iseq->compile_data->last_line = nd_line(node); + debug_nodeprint(node); + + type = nd_type(node); + + switch (type) { + + case NODE_METHOD:{ + /* OK */ + bp(); + COMPILE_ERROR(("BUG: unknown node: NODE_METHOD")); + break; + } + case NODE_FBODY:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_FBODY")); + break; + } + case NODE_CFUNC:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_CFUNC")); + break; + } + case NODE_SCOPE:{ + /* OK */ + COMPILE_ERROR(("BUG: shouldn't reach: NODE_SCOPE")); + break; + } + case NODE_BLOCK:{ + while (node && nd_type(node) == NODE_BLOCK) { + COMPILE_(ret, "BLOCK body", node->nd_head, + (node->nd_next == 0 && poped == 0) ? 0 : 1); + node = node->nd_next; + } + if (node) { + COMPILE_(ret, "BLOCK next", node->nd_next, poped); + } + break; + } + case NODE_IF:{ + DECL_ANCHOR(cond_seq); + DECL_ANCHOR(then_seq); + DECL_ANCHOR(else_seq); + LABEL *then_label, *else_label, *end_label; + + then_label = NEW_LABEL(nd_line(node)); + else_label = NEW_LABEL(nd_line(node)); + end_label = NEW_LABEL(nd_line(node)); + + compile_branch_condition(iseq, cond_seq, node->nd_cond, + then_label, else_label); + COMPILE_(then_seq, "then", node->nd_body, poped); + COMPILE_(else_seq, "else", node->nd_else, poped); + + ADD_SEQ(ret, cond_seq); + + ADD_LABEL(ret, then_label); + ADD_SEQ(ret, then_seq); + ADD_INSNL(ret, nd_line(node), jump, end_label); + + ADD_LABEL(ret, else_label); + ADD_SEQ(ret, else_seq); + + ADD_LABEL(ret, end_label); + + break; + } + case NODE_CASE:{ + NODE *vals; + NODE *val; + NODE *tempnode = node; + LABEL *endlabel, *elselabel; + DECL_ANCHOR(head); + DECL_ANCHOR(body_seq); + DECL_ANCHOR(cond_seq); + VALUE special_literals = rb_ary_new(); + + if (node->nd_head == 0) { + COMPILE_(ret, "when", node->nd_body, poped); + break; + } + COMPILE(head, "case base", node->nd_head); + + node = node->nd_body; + type = nd_type(node); + + if (type != NODE_WHEN) { + COMPILE_ERROR(("NODE_CASE: unexpected node. must be NODE_WHEN, but %s", node_name(type))); + } + + endlabel = NEW_LABEL(nd_line(node)); + elselabel = NEW_LABEL(nd_line(node)); + + ADD_SEQ(ret, head); /* case VAL */ + + while (type == NODE_WHEN) { + LABEL *l1; + + l1 = NEW_LABEL(nd_line(node)); + ADD_LABEL(body_seq, l1); + ADD_INSN(body_seq, nd_line(node), pop); + COMPILE_(body_seq, "when body", node->nd_body, poped); + ADD_INSNL(body_seq, nd_line(node), jump, endlabel); + + vals = node->nd_head; + if (vals) { + if (nd_type(vals) == NODE_ARRAY) { + special_literals = when_vals(iseq, cond_seq, vals, l1, special_literals); + } + else if (nd_type(vals) == NODE_SPLAT || nd_type(vals) == NODE_ARGSCAT) { + NODE *val = vals->nd_head; + special_literals = 0; + + if (nd_type(vals) == NODE_ARGSCAT) { + when_vals(iseq, cond_seq, vals->nd_head, l1, 0); + val = vals->nd_body; + } + + COMPILE(cond_seq, "when/cond splat", val); + ADD_INSN1(cond_seq, nd_line(val), checkincludearray, Qtrue); + ADD_INSNL(cond_seq, nd_line(val), branchif, l1); + } + else { + rb_bug("NODE_CASAE: unknown node (%s)", node_name(nd_type(vals))); + } + } + else { + rb_bug("NODE_CASAE: must be NODE_ARRAY, but 0\n"); + } + + node = node->nd_next; + if (!node) { + break; + } + type = nd_type(node); + } + /* else */ + if (node) { + ADD_LABEL(cond_seq, elselabel); + ADD_INSN(cond_seq, nd_line(node), pop); + COMPILE_(cond_seq, "else", node, poped); + ADD_INSNL(cond_seq, nd_line(node), jump, endlabel); + } + else { + debugs("== else (implicit)\n"); + ADD_LABEL(cond_seq, elselabel); + ADD_INSN(cond_seq, nd_line(tempnode), pop); + if (!poped) { + ADD_INSN(cond_seq, nd_line(tempnode), putnil); + } + ADD_INSNL(cond_seq, nd_line(tempnode), jump, endlabel); + } + + if (special_literals) { + ADD_INSN(ret, nd_line(tempnode), dup); + ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, + special_literals, elselabel); + iseq_add_mark_object_compile_time(iseq, special_literals); + } + + ADD_SEQ(ret, cond_seq); + ADD_SEQ(ret, body_seq); + ADD_LABEL(ret, endlabel); + break; + } + case NODE_WHEN:{ + NODE *vals; + NODE *val; + NODE *orig_node = node; + LABEL *endlabel; + DECL_ANCHOR(body_seq); + + endlabel = NEW_LABEL(nd_line(node)); + + while (node && nd_type(node) == NODE_WHEN) { + LABEL *l1 = NEW_LABEL(nd_line(node)); + ADD_LABEL(body_seq, l1); + COMPILE_(body_seq, "when", node->nd_body, poped); + ADD_INSNL(body_seq, nd_line(node), jump, endlabel); + + vals = node->nd_head; + if (vals && nd_type(vals) == NODE_ARRAY) { + while (vals) { + val = vals->nd_head; + COMPILE(ret, "when2", val); + ADD_INSNL(ret, nd_line(val), branchif, l1) ; + vals = vals->nd_next; + } + } + else if (nd_type(vals) == NODE_SPLAT || nd_type(vals) == NODE_ARGSCAT) { + NODE *val = vals->nd_head; + + if (nd_type(vals) == NODE_ARGSCAT) { + NODE *vs = vals->nd_head; + val = vals->nd_body; + + while (vs) { + NODE* val = vs->nd_head; + COMPILE(ret, "when/argscat", val); + ADD_INSNL(ret, nd_line(val), branchif, l1); + vs = vs->nd_next; + } + } + + ADD_INSN(ret, nd_line(val), putnil); + COMPILE(ret, "when2/splat", val); + ADD_INSN1(ret, nd_line(val), checkincludearray, Qfalse); + ADD_INSN(ret, nd_line(val), pop); + ADD_INSNL(ret, nd_line(val), branchif, l1); + } + else { + rb_bug("err"); + } + node = node->nd_next; + } + /* else */ + COMPILE_(ret, "else", node, poped); + ADD_INSNL(ret, nd_line(orig_node), jump, endlabel); + + ADD_SEQ(ret, body_seq); + ADD_LABEL(ret, endlabel); + + break; + } + case NODE_OPT_N: + case NODE_WHILE: + case NODE_UNTIL:{ + LABEL *prev_start_label = iseq->compile_data->start_label; + LABEL *prev_end_label = iseq->compile_data->end_label; + LABEL *prev_redo_label = iseq->compile_data->redo_label; + VALUE prev_loopval_popped = iseq->compile_data->loopval_popped; + + struct iseq_compile_data_ensure_node_stack *enlp = + iseq->compile_data->ensure_node_stack; + + LABEL *next_label = iseq->compile_data->start_label = NEW_LABEL(nd_line(node)); /* next */ + LABEL *redo_label = iseq->compile_data->redo_label = NEW_LABEL(nd_line(node)); /* redo */ + LABEL *break_label = iseq->compile_data->end_label = NEW_LABEL(nd_line(node)); /* break */ + LABEL *end_label = NEW_LABEL(nd_line(node)); + + iseq->compile_data->loopval_popped = 0; + iseq->compile_data->ensure_node_stack = 0; + + if (type == NODE_OPT_N || node->nd_state) { + ADD_INSNL(ret, nd_line(node), jump, next_label); + } + + ADD_LABEL(ret, redo_label); + COMPILE_POPED(ret, "while body", node->nd_body); + ADD_LABEL(ret, next_label); /* next */ + + if (type == NODE_WHILE) { + compile_branch_condition(iseq, ret, node->nd_cond, + redo_label, end_label); + } + else if (type == NODE_UNTIL) { + /* untile */ + compile_branch_condition(iseq, ret, node->nd_cond, + end_label, redo_label); + } + else { + ADD_INSN(ret, nd_line(node), putself); + ADD_CALL(ret, nd_line(node), ID2SYM(idGets), INT2FIX(0)); + ADD_INSNL(ret, nd_line(node), branchif, redo_label) ; + /* opt_n */ + } + + ADD_LABEL(ret, end_label); + + if (node->nd_state == Qundef) { + ADD_INSN(ret, nd_line(node), putundef); + } + else { + ADD_INSN(ret, nd_line(node), putnil); + } + + ADD_LABEL(ret, break_label); /* braek */ + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + + ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, redo_label, break_label, + 0, break_label); + ADD_CATCH_ENTRY(CATCH_TYPE_NEXT | 0x10000, redo_label, + break_label, 0, iseq->compile_data->start_label); + ADD_CATCH_ENTRY(CATCH_TYPE_REDO, redo_label, break_label, 0, + iseq->compile_data->redo_label); + + iseq->compile_data->start_label = prev_start_label; + iseq->compile_data->end_label = prev_end_label; + iseq->compile_data->redo_label = prev_redo_label; + iseq->compile_data->loopval_popped = prev_loopval_popped; + iseq->compile_data->ensure_node_stack = enlp; + break; + } + case NODE_ITER: + case NODE_FOR:{ + VALUE prevblock = iseq->compile_data->current_block; + LABEL *retry_label = NEW_LABEL(nd_line(node)); + LABEL *retry_end_l = NEW_LABEL(nd_line(node)); + ID mid = 0; + + ADD_LABEL(ret, retry_label); + if (nd_type(node) == NODE_FOR) { + COMPILE(ret, "iter caller (for)", node->nd_iter); + + iseq->compile_data->current_block = + NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq), + ISEQ_TYPE_BLOCK); + + mid = idEach; + ADD_SEND_R(ret, nd_line(node), ID2SYM(idEach), INT2FIX(0), + iseq->compile_data->current_block, INT2FIX(0)); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + } + else { + iseq->compile_data->current_block = + NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq), + ISEQ_TYPE_BLOCK); + COMPILE_(ret, "iter caller", node->nd_iter, poped); + } + ADD_LABEL(ret, retry_end_l); + iseq->compile_data->current_block = prevblock; + + ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, retry_label, retry_end_l, 0, + retry_label); + break; + } + case NODE_BREAK:{ + unsigned long level = 0; + + if (iseq->compile_data->redo_label != 0) { + /* while/until */ + add_ensure_iseq(ret, iseq); + COMPILE_(ret, "break val (while/until)", node->nd_stts, + iseq->compile_data->loopval_popped); + ADD_INSNL(ret, nd_line(node), jump, + iseq->compile_data->end_label); + } + else if (iseq->type == ISEQ_TYPE_BLOCK) { + break_by_insn: + /* escape from block */ + COMPILE(ret, "break val (block)", node->nd_stts); + ADD_INSN1(ret, nd_line(node), throw, + INT2FIX(level | 0x02) /* TAG_BREAK */ ); + } + else if (iseq->type == ISEQ_TYPE_EVAL) { + COMPILE_ERROR(("Can't escape from eval with break")); + } + else { + yarv_iseq_t *ip = iseq->parent_iseq; + while (ip) { + level++; + if (ip->compile_data->redo_label != 0) { + level = 0x8000; + if (ip->compile_data->loopval_popped == 0) { + /* need value */ + level |= 0x4000; + } + goto break_by_insn; + } + else if (ip->type == ISEQ_TYPE_BLOCK) { + level <<= 16; + goto break_by_insn; + } + ip = ip->parent_iseq; + } + COMPILE_ERROR(("Illegal break")); + } + break; + } + case NODE_NEXT:{ + unsigned long level = 0; + + if (iseq->compile_data->redo_label != 0) { + add_ensure_iseq(ret, iseq); + ADD_INSNL(ret, nd_line(node), jump, + iseq->compile_data->start_label); + } + else if (iseq->compile_data->end_label) { + COMPILE(ret, "next val", node->nd_stts); + add_ensure_iseq(ret, iseq); + ADD_INSNL(ret, nd_line(node), jump, + iseq->compile_data->end_label); + } + else if (iseq->type == ISEQ_TYPE_EVAL) { + COMPILE_ERROR(("Can't escape from eval with next")); + } + else { + yarv_iseq_t *ip = iseq->parent_iseq; + while (ip) { + level = 0x8000; + if (ip->type == ISEQ_TYPE_BLOCK) { + level |= 0x4000; + break; + } + else if (ip->compile_data->redo_label != 0) { + break; + } + ip = ip->parent_iseq; + } + if (ip != 0) { + COMPILE(ret, "next val", node->nd_stts); + add_ensure_iseq(ret, iseq); + ADD_INSN1(ret, nd_line(node), throw, + INT2FIX(level | 0x03) /* TAG_NEXT */ ); + } + else { + COMPILE_ERROR(("Illegal next")); + } + } + break; + } + case NODE_REDO:{ + if (iseq->compile_data->redo_label) { + add_ensure_iseq(ret, iseq); + ADD_INSNL(ret, nd_line(node), jump, + iseq->compile_data->redo_label); + if (!poped) { /* for stack consistency */ + ADD_INSN(ret, nd_line(node), putnil); + } + } + else if (iseq->type == ISEQ_TYPE_EVAL) { + COMPILE_ERROR(("Can't escape from eval with redo")); + } + else if (iseq->compile_data->start_label) { + ADD_INSNL(ret, nd_line(node), jump, + iseq->compile_data->start_label); + if (!poped) { /* for stack consistency */ + ADD_INSN(ret, nd_line(node), putnil); + } + } + else { + yarv_iseq_t *ip = iseq->parent_iseq; + unsigned long level = 0x8000 | 0x4000; + while (ip) { + if (ip->type == ISEQ_TYPE_BLOCK) { + break; + } + else if (ip->type == ISEQ_TYPE_EVAL) { + COMPILE_ERROR(("Can't escape from eval with redo")); + } + else if (ip->compile_data->redo_label != 0) { + break; + } + ip = ip->parent_iseq; + } + if (ip != 0) { + add_ensure_iseq(ret, iseq); + ADD_INSN1(ret, nd_line(node), throw, + INT2FIX(level | 0x05) /* TAG_REDO */ ); + } + else { + COMPILE_ERROR(("Illegal redo")); + } + } + break; + } + case NODE_RETRY:{ + if (iseq->type == ISEQ_TYPE_BLOCK || + iseq->type == ISEQ_TYPE_RESCUE) { + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN1(ret, nd_line(node), throw, + INT2FIX(0x04) /* TAG_RETRY */ ); + } + else { + COMPILE_ERROR(("Illegal retry")); + } + break; + } + case NODE_BEGIN:{ + COMPILE_(ret, "NODE_BEGIN", node->nd_body, poped); + break; + } + case NODE_RESCUE:{ + LABEL *lstart = NEW_LABEL(nd_line(node)); + LABEL *lend = NEW_LABEL(nd_line(node)); + LABEL *lcont = NEW_LABEL(nd_line(node)); + VALUE rescue = NEW_CHILD_ISEQVAL(node->nd_resq, + rb_str_concat(rb_str_new2 + ("rescue in "), + iseq->name), + ISEQ_TYPE_RESCUE); + + ADD_LABEL(ret, lstart); + COMPILE(ret, "rescue head", node->nd_head); + ADD_LABEL(ret, lend); + if (node->nd_else) { + ADD_INSN(ret, nd_line(node), pop); + COMPILE(ret, "rescue else", node->nd_else); + } + ADD_INSN(ret, nd_line(node), nop); + ADD_LABEL(ret, lcont); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + + /* resgister catch entry */ + ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont); + ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, 0, lstart); + break; + } + case NODE_RESBODY:{ + NODE *resq = node; + NODE *narg; + LABEL *label_miss, *label_hit; + + while (resq) { + label_miss = NEW_LABEL(nd_line(node)); + label_hit = NEW_LABEL(nd_line(node)); + + narg = resq->nd_args; + while (narg) { + COMPILE(ret, "rescue arg", narg->nd_head); + ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), + INT2FIX(0)); + ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1)); + ADD_INSNL(ret, nd_line(node), branchif, label_hit) ; + narg = narg->nd_next; + } + if (resq->nd_args == 0) { + ADD_INSN1(ret, nd_line(node), putobject, + rb_eStandardError); + ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), + INT2FIX(0)); + ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1)); + ADD_INSNL(ret, nd_line(node), branchif, label_hit) ; + } + ADD_INSNL(ret, nd_line(node), jump, label_miss); + ADD_LABEL(ret, label_hit); + COMPILE(ret, "resbody body", resq->nd_body); + ADD_INSN(ret, nd_line(node), leave); + ADD_LABEL(ret, label_miss); + resq = resq->nd_head; + } + break; + } + case NODE_ENSURE:{ + DECL_ANCHOR(ensr); + VALUE ensure = NEW_CHILD_ISEQVAL(node->nd_ensr, + rb_str_concat(rb_str_new2 + ("ensure in "), + iseq->name), + ISEQ_TYPE_ENSURE); + LABEL *lstart = NEW_LABEL(nd_line(node)); + LABEL *lend = NEW_LABEL(nd_line(node)); + LABEL *lcont = NEW_LABEL(nd_line(node)); + 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 */ + &er, + }; + struct ensure_range *erange; + + COMPILE_POPED(ensr, "ensure ensr", node->nd_ensr); + + iseq->compile_data->ensure_node_stack = &enl; + + ADD_LABEL(ret, lstart); + COMPILE_(ret, "ensure head", node->nd_head, poped); + ADD_LABEL(ret, lend); + if (ensr->anchor.next == 0) { + ADD_INSN(ret, nd_line(node), nop); + } + else { + ADD_SEQ(ret, ensr); + } + ADD_LABEL(ret, lcont); + + erange = iseq->compile_data->ensure_node_stack->erange; + while (erange) { + ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end, + ensure, lcont); + erange = erange->next; + } + iseq->compile_data->ensure_node_stack = enl.prev; + break; + } + + case NODE_AND: + case NODE_OR:{ + LABEL *end_label = NEW_LABEL(nd_line(node)); + COMPILE(ret, "nd_1st", node->nd_1st); + if (!poped) { + ADD_INSN(ret, nd_line(node), dup); + } + if (type == NODE_AND) { + ADD_INSNL(ret, nd_line(node), branchunless, end_label); + } + else { + ADD_INSNL(ret, nd_line(node), branchif, end_label) ; + } + if (!poped) { + ADD_INSN(ret, nd_line(node), pop); + } + COMPILE_(ret, "nd_2nd", node->nd_2nd, poped); + ADD_LABEL(ret, end_label); + break; + } + case NODE_NOT:{ + COMPILE(ret, "value", node->nd_body); + ADD_INSN(ret, nd_line(node), putnot); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + + case NODE_MASGN:{ + compile_massign(iseq, ret, node->nd_value, /* rhsn */ + node->nd_args, /* splat */ + node->nd_head, /* lhsn */ + 0); + if (!poped) { + ADD_INSN1(ret, nd_line(node), putobject, Qtrue); + } + break; + } + + case NODE_LASGN:{ + int idx = iseq->local_iseq->local_size + 2 - node->nd_cnt; + debugs("lvar: %d\n", idx); + COMPILE(ret, "lvalue", node->nd_value); + + if (!poped) { + ADD_INSN(ret, nd_line(node), dup); + } + ADD_INSN1(ret, nd_line(node), setlocal, INT2FIX(idx)); + + break; + } + case NODE_DASGN: + case NODE_DASGN_CURR:{ + int idx, lv, ls; + COMPILE(ret, "dvalue", node->nd_value); + debugp_param("dassn id", rb_str_new2(rb_id2name(node->nd_vid))); + + if (!poped) { + ADD_INSN(ret, nd_line(node), dup); + } + idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); + if (nd_type(node) == NODE_DASGN_CURR && + lv > 0 && + iseq->type == ISEQ_TYPE_BLOCK && + iseq->compile_data->for_iseq != 1) { + + dpi(node->nd_vid); + rb_bug("NODE_DASGN_CURR, but lv == %d (line: %d)", lv, + nd_line(node)); + } + + if (idx < 0) { + debugi("unknown id", node->nd_vid); + COMPILE_ERROR(("NODE_DASGN error")); + } + ADD_INSN2(ret, nd_line(node), setdynamic, + INT2FIX(ls - idx), INT2FIX(lv)); + break; + } + case NODE_GASGN:{ + COMPILE(ret, "lvalue", node->nd_value); + + if (!poped) { + ADD_INSN(ret, nd_line(node), dup); + } + ADD_INSN1(ret, nd_line(node), setglobal, + (((long)node->nd_entry) | 1)); + break; + } + case NODE_IASGN:{ + COMPILE(ret, "lvalue", node->nd_value); + if (!poped) { + ADD_INSN(ret, nd_line(node), dup); + } + ADD_INSN1(ret, nd_line(node), setinstancevariable, + ID2SYM(node->nd_vid)); + break; + } + case NODE_CDECL:{ + COMPILE(ret, "lvalue", node->nd_value); + + if (!poped) { + ADD_INSN(ret, nd_line(node), dup); + } + + if (node->nd_vid) { + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN1(ret, nd_line(node), setconstant, + ID2SYM(node->nd_vid)); + } + else { + compile_cpath(ret, iseq, node->nd_else); + ADD_INSN1(ret, nd_line(node), setconstant, + ID2SYM(node->nd_else->nd_mid)); + } + break; + } + case NODE_CVASGN: + case NODE_CVDECL:{ + COMPILE(ret, "cvasgn val", node->nd_value); + if (!poped) { + ADD_INSN(ret, nd_line(node), dup); + } + ADD_INSN2(ret, nd_line(node), setclassvariable, + ID2SYM(node->nd_vid), + nd_type(node) == NODE_CVDECL ? Qtrue : Qfalse); + break; + } + case NODE_OP_ASGN1:{ + DECL_ANCHOR(args); + int argc; + ID id = node->nd_mid; + + /* + * a[x] (op)= y + * + * eval a # a + * eval x # a x + * dupn 2 # a x a x + * send :[] # a x a[x] + * eval y # a x a[x] y + * send op # a x a[x]+y + * send []= # ret + */ + + /* + * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head; + * NODE_OP_ASGN nd_recv + * nd_args->nd_head + * nd_args->nd_body + * nd_mid + */ + + COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv); + argc = compile_array(iseq, args, node->nd_args->nd_body, Qfalse); + POP_ELEMENT(args); + ADD_SEQ(ret, args); + ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(argc+1)); + ADD_SEND(ret, nd_line(node), ID2SYM(idAREF), INT2FIX(argc)); + + if (id == 0 || id == 1) { + /* 0: or, 1: and + a[x] ||= y + + unless/if a[x] + a[x]= y + else + nil + end + */ + LABEL *label = NEW_LABEL(nd_line(node)); + LABEL *lfin = NEW_LABEL(nd_line(node)); + + if (id == 0) { + /* or */ + ADD_INSN(ret, nd_line(node), dup); + ADD_INSNL(ret, nd_line(node), branchif, label) ; + ADD_INSN(ret, nd_line(node), pop); + } + else { + /* and */ + ADD_INSNL(ret, nd_line(node), branchunless, label); + } + + COMPILE(ret, "NODE_OP_ASGN1 args->head: ", + node->nd_args->nd_head); + ADD_SEND(ret, nd_line(node), ID2SYM(idASET), + INT2FIX(argc + 1)); + ADD_INSNL(ret, nd_line(node), jump, lfin); + ADD_LABEL(ret, label); + if (id == 0) { /* or */ + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN(ret, nd_line(node), pop); + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN(ret, nd_line(node), pop); + } + else if (id == 1) { /* and */ + ADD_INSN(ret, nd_line(node), pop); + ADD_INSN(ret, nd_line(node), pop); + ADD_INSN(ret, nd_line(node), putnil); + } + ADD_LABEL(ret, lfin); + } + else { + COMPILE(ret, "NODE_OP_ASGN1 args->head: ", + node->nd_args->nd_head); + ADD_SEND(ret, nd_line(node), ID2SYM(id), INT2FIX(1)); + ADD_SEND(ret, nd_line(node), ID2SYM(idASET), + INT2FIX(argc + 1)); + } + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + + break; + } + case NODE_OP_ASGN2:{ + ID atype = node->nd_next->nd_mid; + LABEL *lfin = NEW_LABEL(nd_line(node)); + LABEL *lcfin = NEW_LABEL(nd_line(node)); + /* + class C; attr_accessor :c; end + r = C.new + r.a &&= v # asgn2 + + eval r # r + dup # r r + eval r.a # r o + + # or + dup # r o o + if lcfin # r o + pop # r + eval v # r v + send a= # v + jump lfin # v + + lcfin: # r o + swap # o r + pop # o + + lfin: # v + + # and + dup # r o o + unless lcfin + pop # r + eval v # r v + send a= # v + jump lfin # v + + # others + eval v # r o v + send ?? # r w + send a= # w + + */ + + COMPILE(ret, "NODE_OP_ASGN2#recv", node->nd_recv); + ADD_INSN(ret, nd_line(node), dup); + ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_vid), + INT2FIX(0)); + + if (atype == 0 || atype == 1) { /* 0: OR or 1: AND */ + ADD_INSN(ret, nd_line(node), dup); + if (atype == 0) { + ADD_INSNL(ret, nd_line(node), branchif, lcfin) ; + } + else { + ADD_INSNL(ret, nd_line(node), branchunless, lcfin); + } + ADD_INSN(ret, nd_line(node), pop); + COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); + ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_aid), + INT2FIX(1)); + ADD_INSNL(ret, nd_line(node), jump, lfin); + + ADD_LABEL(ret, lcfin); + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN(ret, nd_line(node), pop); + + ADD_LABEL(ret, lfin); + } + else { + COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); + ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_mid), + INT2FIX(1)); + ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_aid), + INT2FIX(1)); + } + + if (poped) { + /* we can apply more optimize */ + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_OP_ASGN_AND: + case NODE_OP_ASGN_OR:{ + LABEL *lfin = NEW_LABEL(nd_line(node)); + LABEL *lassign = NEW_LABEL(nd_line(node)); + + if (nd_type(node) == NODE_OP_ASGN_OR) { + defined_expr(iseq, ret, node->nd_head, lassign, Qfalse); + ADD_INSNL(ret, nd_line(node), branchunless, lassign); + } + + COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head); + ADD_INSN(ret, nd_line(node), dup); + + if (nd_type(node) == NODE_OP_ASGN_AND) { + ADD_INSNL(ret, nd_line(node), branchunless, lfin); + } + else { + ADD_INSNL(ret, nd_line(node), branchif, lfin) ; + } + + ADD_INSN(ret, nd_line(node), pop); + ADD_LABEL(ret, lassign); + COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value); + ADD_LABEL(ret, lfin); + + if (poped) { + /* we can apply more optimize */ + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_CALL: + case NODE_FCALL: + case NODE_VCALL:{ /* VCALL: variable or call */ + /* + call: obj.method(...) + fcall: func(...) + vcall: func + */ + DECL_ANCHOR(recv); + DECL_ANCHOR(args); + ID mid = node->nd_mid; + VALUE argc; + VALUE flag = 0; + VALUE parent_block = iseq->compile_data->current_block; + iseq->compile_data->current_block = Qfalse; + +#if SUPPORT_JOKE + if (nd_type(node) == NODE_VCALL) { + if (mid == idBitblt) { + ADD_INSN(ret, nd_line(node), bitblt); + break; + } + else if (mid == idAnswer) { + ADD_INSN(ret, nd_line(node), answer); + break; + } + } + /* only joke */ + { + static ID goto_id; + static ID label_id; + VALUE label; + VALUE label_sym; + + if (goto_id == 0) { + goto_id = rb_intern("__goto__"); + label_id = rb_intern("__label__"); + } + + if (nd_type(node) == NODE_FCALL && + (mid == goto_id || mid == label_id)) { + if (nd_type(node->nd_args->nd_head) == NODE_LIT && + SYMBOL_P(node->nd_args->nd_head->nd_lit)) { + + label_sym = label = node->nd_args->nd_head->nd_lit; + if ((label = + rb_hash_aref(iseq->compile_data, + label_sym)) == Qnil) { + rb_hash_aset(iseq->compile_data, label_sym, + label = NEW_LABEL(nd_line(node))); + } + } + else { + rb_bug("illegal goto/label format"); + } + + + if (mid == goto_id) { + ADD_INSNL(ret, nd_line(node), jump, label); + } + else { + ADD_LABEL(ret, label); + } + break; + } + } +#endif + /* reciever */ + if (type == NODE_CALL) { + COMPILE(recv, "recv", node->nd_recv); + } + else if (type == NODE_FCALL || type == NODE_VCALL) { + ADD_INSN(recv, nd_line(node), putself); + } + + /* args */ + if (nd_type(node) != NODE_VCALL) { + argc = setup_arg(iseq, args, node, &flag); + } + else { + argc = INT2FIX(0); + } + + ADD_SEQ(ret, recv); + ADD_SEQ(ret, args); + + debugp_param("call args argc", argc); + debugp_param("call method", ID2SYM(mid)); + + switch (nd_type(node)) { + case NODE_VCALL: + flag |= VM_CALL_VCALL_BIT; + /* VCALL is funcall, so fall through */ + case NODE_FCALL: + flag |= VM_CALL_FCALL_BIT; + } + + ADD_SEND_R(ret, nd_line(node), ID2SYM(mid), + argc, parent_block, INT2FIX(flag)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_SUPER: + case NODE_ZSUPER:{ + DECL_ANCHOR(args); + VALUE argc; + VALUE flag = 0; + VALUE parent_block = iseq->compile_data->current_block; + iseq->compile_data->current_block = Qfalse; + + if (nd_type(node) == NODE_SUPER) { + argc = setup_arg(iseq, args, node, &flag); + } + else { + /* NODE_ZSUPER */ + int i; + yarv_iseq_t *liseq = iseq->local_iseq; + + argc = INT2FIX(liseq->argc); + + /* normal arguments */ + for (i = 0; i < liseq->argc; i++) { + int idx = liseq->local_size - i; + ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx)); + } + if (!liseq->arg_simple) { + if (liseq->arg_opts) { + /* optional arguments */ + int j; + for (j = 0; j < liseq->arg_opts - 1; j++) { + int idx = liseq->local_size - (i + j); + ADD_INSN1(args, nd_line(node), getlocal, + INT2FIX(idx)); + } + i += j; + argc = INT2FIX(i); + } + if (liseq->arg_rest) { + /* rest arguments */ + int idx = liseq->local_size - liseq->arg_rest + 1; + ADD_INSN1(args, nd_line(node), getlocal, + INT2FIX(idx)); + argc = INT2FIX(liseq->arg_rest); + flag |= VM_CALL_ARGS_SPLAT_BIT; + } + } + } + + /* dummy reciever */ + ADD_INSN1(ret, nd_line(node), putobject, + nd_type(node) == NODE_ZSUPER ? Qfalse : Qtrue); + ADD_SEQ(ret, args); + ADD_INSN3(ret, nd_line(node), invokesuper, + argc, parent_block, INT2FIX(flag)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_ARRAY:{ + compile_array(iseq, ret, node, Qtrue); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_ZARRAY:{ + if (!poped) { + ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(0)); + } + break; + } + case NODE_VALUES:{ + NODE *n = node; + while (n) { + COMPILE(ret, "values item", n->nd_head); + n = n->nd_next; + } + ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(node->nd_alen)); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_HASH:{ + DECL_ANCHOR(list); + VALUE size = 0; + int type = node->nd_head ? nd_type(node->nd_head) : NODE_ZARRAY; + + switch (type) { + case NODE_ARRAY:{ + compile_array(iseq, list, node->nd_head, Qfalse); + size = OPERAND_AT(POP_ELEMENT(list), 0); + ADD_SEQ(ret, list); + break; + } + case NODE_ZARRAY: + size = INT2FIX(0); + break; + + default: + rb_bug("can't make hash with this node: %s", node_name(type)); + } + + ADD_INSN1(ret, nd_line(node), newhash, size); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_RETURN:{ + yarv_iseq_t *is = iseq; + + while (is) { + if (is->type == ISEQ_TYPE_TOP || is->type == ISEQ_TYPE_CLASS) { + COMPILE_ERROR(("Illegal return")); + break; + } + else { + if (is->type == ISEQ_TYPE_METHOD) { + ADD_INSN(ret, nd_line(node), emptstack); + } + + COMPILE(ret, "return nd_stts (return val)", + node->nd_stts); + + if (is->type == ISEQ_TYPE_METHOD) { + add_ensure_iseq(ret, iseq); + ADD_INSN(ret, nd_line(node), leave); + } + else { + ADD_INSN1(ret, nd_line(node), throw, + INT2FIX(0x01) /* TAG_RETURN */ ); + } + break; + } + } + + break; + } + case NODE_YIELD:{ + DECL_ANCHOR(args); + int argc; + unsigned long flag = 0; + + if (iseq->type == ISEQ_TYPE_TOP || iseq->type == ISEQ_TYPE_CLASS) { + COMPILE_ERROR(("Illegal yield")); + } + + if (node->nd_head) { + if (nd_type(node->nd_head) == NODE_ARRAY) { + NODE *p; + for (argc = 0, p = node->nd_head; p; + p = p->nd_next, argc++) { + /* count argc */ + } + if (argc == 1) { + COMPILE(args, "yield with an arg", node->nd_head); + } + else { + compile_array(iseq, args, node->nd_head, Qfalse); + POP_ELEMENT(args); + } + debugs("argc: %d\n", argc); + } + else { + if (nd_type(node->nd_head) == NODE_ARGSCAT) { + if (node->nd_state == 2) { + flag |= VM_CALL_ARGS_SPLAT_BIT; + } + + compile_array(iseq, args, node->nd_head->nd_head, + Qfalse); + POP_ELEMENT(args); + argc = LIST_SIZE(args) + 1; + + COMPILE(args, "args(cat: splat)", + node->nd_head->nd_body); + } + else if (nd_type(node->nd_head) == NODE_SPLAT) { + if (node->nd_state == 2) { + flag |= VM_CALL_ARGS_SPLAT_BIT; + } + + argc = 1; + COMPILE(args, "splat", node->nd_head->nd_head); + } + else { + COMPILE(args, "nd_head(1)", node->nd_head); + argc = 1; + } + } + } + else { + argc = 0; + } + ADD_SEQ(ret, args); + ADD_INSN2(ret, nd_line(node), invokeblock, INT2FIX(argc), + INT2FIX(flag)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_LVAR:{ + if (!poped) { + int idx = iseq->local_iseq->local_size + 2 - node->nd_cnt; + debugs("idx: %d\n", idx); + ADD_INSN1(ret, nd_line(node), getlocal, INT2FIX(idx)); + } + break; + } + case NODE_DVAR:{ + int lv, idx, ls; + debugi("nd_vid", node->nd_vid); + if (!poped) { + idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); + if (idx < 0) { + rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid)); + } + ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx), + INT2FIX(lv)); + } + break; + } + case NODE_GVAR:{ + ADD_INSN1(ret, nd_line(node), getglobal, + (((long)node->nd_entry) | 1)); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_IVAR:{ + debugi("nd_vid", node->nd_vid); + if (!poped) { + ADD_INSN1(ret, nd_line(node), getinstancevariable, + ID2SYM(node->nd_vid)); + } + break; + } + case NODE_CONST:{ + debugi("nd_vid", node->nd_vid); + + if (iseq->compile_data->option->inline_const_cache) { + LABEL *lstart = NEW_LABEL(nd_line(node)); + LABEL *lend = NEW_LABEL(nd_line(node)); + + ADD_LABEL(ret, lstart); + ADD_INSN2(ret, nd_line(node), getinlinecache, + NEW_INLINE_CACHE_ENTRY(), lend); + ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_vid)); + ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_LABEL(ret, lend); + } + else { + ADD_INSN(ret, nd_line(node), putnil); + ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_vid)); + } + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_CVAR:{ + if (!poped) { + ADD_INSN1(ret, nd_line(node), getclassvariable, + ID2SYM(node->nd_vid)); + } + break; + } + case NODE_NTH_REF:{ + ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(node->nd_cnt), + INT2FIX(node->nd_nth << 1)); + break; + } + case NODE_BACK_REF:{ + ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(node->nd_cnt), + INT2FIX(0x01 | (node->nd_nth << 1))); + break; + } + case NODE_MATCH: + case NODE_MATCH2: + case NODE_MATCH3:{ + DECL_ANCHOR(recv); + DECL_ANCHOR(val); + + switch(nd_type(node)) { + case NODE_MATCH: + ADD_INSN1(recv, nd_line(node), putobject, node->nd_lit); + ADD_INSN2(val, nd_line(node), getspecial, INT2FIX(0), + INT2FIX(0)); + break; + case NODE_MATCH2: + COMPILE(recv, "reciever", node->nd_recv); + COMPILE(val, "value", node->nd_value); + break; + case NODE_MATCH3: + COMPILE(recv, "reciever", node->nd_value); + COMPILE(val, "value", node->nd_recv); + break; + } + + if (iseq->compile_data->option->specialized_instruction) { + /* TODO: detect by node */ + if (recv->last == recv->anchor.next && + INSN_OF(recv->last) == BIN(putobject) && + nd_type(node) == NODE_MATCH2) { + ADD_SEQ(ret, val); + ADD_INSN1(ret, nd_line(node), opt_regexpmatch1, + OPERAND_AT(recv->last, 0)); + } + else { + ADD_SEQ(ret, recv); + ADD_SEQ(ret, val); + ADD_INSN(ret, nd_line(node), opt_regexpmatch2); + } + } + else { + ADD_SEQ(ret, recv); + ADD_SEQ(ret, val); + ADD_SEND(ret, nd_line(node), ID2SYM(idEqTilde), INT2FIX(1)); + } + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_LIT:{ + debugp_param("lit", node->nd_lit); + if (!poped) { + ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); + } + break; + } + case NODE_STR:{ + debugp_param("nd_lit", node->nd_lit); + if (!poped) { + ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit); + } + break; + } + case NODE_DSTR:{ + compile_dstr(iseq, ret, node); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_XSTR:{ + ADD_INSN(ret, nd_line(node), putself); + ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); + ADD_CALL(ret, nd_line(node), ID2SYM(idBackquote), INT2FIX(1)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_DXSTR:{ + ADD_INSN(ret, nd_line(node), putself); + compile_dstr(iseq, ret, node); + ADD_CALL(ret, nd_line(node), ID2SYM(idBackquote), INT2FIX(1)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_EVSTR:{ + COMPILE(ret, "nd_body", node->nd_body); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + else { + ADD_INSN(ret, nd_line(node), tostring); + } + break; + } + case NODE_DREGX:{ + compile_dstr(iseq, ret, node); + ADD_INSN1(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_DREGX_ONCE:{ + /* fix me: once? */ + LABEL *lstart = NEW_LABEL(nd_line(node)); + LABEL *lend = NEW_LABEL(nd_line(node)); + + ADD_LABEL(ret, lstart); + ADD_INSN2(ret, nd_line(node), onceinlinecache, + NEW_INLINE_CACHE_ENTRY(), lend); + ADD_INSN(ret, nd_line(node), pop); + + compile_dstr(iseq, ret, node); + ADD_INSN1(ret, nd_line(node), toregexp, INT2FIX(node->nd_cflag)); + + ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_LABEL(ret, lend); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_ARGS:{ + /* OK */ + COMPILE_ERROR(("BUG: should not reach here: compile_each#NODE_ARGS")); + break; + } + case NODE_ARGSCAT:{ + COMPILE(ret, "argscat head", node->nd_head); + COMPILE(ret, "argscat body", node->nd_body); + ADD_INSN(ret, nd_line(node), concatarray); + break; + } + case NODE_ARGSPUSH:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_ARGSPUSH")); + break; + } + case NODE_SPLAT:{ + COMPILE(ret, "splat", node->nd_head); + ADD_INSN1(ret, nd_line(node), splatarray, Qfalse); + break; + } + case NODE_TO_ARY:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_TO_ARY")); + break; + } + case NODE_BLOCK_ARG:{ + iseq->arg_block = node->nd_cnt - 2 + 1; + iseq->arg_simple = 0; + break; + } + case NODE_BLOCK_PASS:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_BLOCK_PASS")); + break; + } + case NODE_DEFN:{ + VALUE iseqval = NEW_ISEQVAL(node->nd_defn, + rb_str_new2(rb_id2name(node->nd_mid)), + ISEQ_TYPE_METHOD); + + debugp_param("defn/iseq", iseqval); + + ADD_INSN (ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), definemethod, + ID2SYM(node->nd_mid), iseqval, INT2FIX(0)); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } + debugp_param("defn", iseqval); + break; + } + case NODE_DEFS:{ + VALUE iseqval = NEW_ISEQVAL(node->nd_defn, + rb_str_new2(rb_id2name(node->nd_mid)), + ISEQ_TYPE_METHOD); + + debugp_param("defs/iseq", iseqval); + + COMPILE(ret, "defs: recv", node->nd_recv); + ADD_INSN3(ret, nd_line(node), definemethod, + ID2SYM(node->nd_mid), iseqval, INT2FIX(1)); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } + break; + } + case NODE_ALIAS:{ + VALUE s1, s2; + + if (nd_type(node->u1.node) != NODE_LIT || + nd_type(node->u2.node) != NODE_LIT) { + rb_bug("alias args must be NODE_LIT"); + } + s1 = node->u1.node->nd_lit; + s2 = node->u2.node->nd_lit; + + ADD_INSN3(ret, nd_line(node), alias, Qfalse, ID2SYM(rb_to_id(s1)), + ID2SYM(rb_to_id(s2))); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } + break; + } + case NODE_VALIAS:{ + ADD_INSN3(ret, nd_line(node), alias, Qtrue, ID2SYM(node->u1.id), + ID2SYM(node->u2.id)); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } + break; + } + case NODE_UNDEF:{ + if (nd_type(node->u2.node) != NODE_LIT) { + rb_bug("undef args must be NODE_LIT"); + } + ADD_INSN1(ret, nd_line(node), undef, + ID2SYM(rb_to_id(node->u2.node->nd_lit))); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } + break; + } + case NODE_CLASS:{ + VALUE iseqval = + NEW_CHILD_ISEQVAL( + node->nd_body, + make_name_with_str("<class:%s>", + rb_id2name(node->nd_cpath->nd_mid)), + ISEQ_TYPE_CLASS); + compile_cpath(ret, iseq, node->nd_cpath); + COMPILE(ret, "super", node->nd_super); + ADD_INSN3(ret, nd_line(node), defineclass, + ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(0)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_MODULE:{ + VALUE iseqval = NEW_CHILD_ISEQVAL(node->nd_body, + make_name_with_str + ("<module:%s>", + rb_id2name(node->nd_cpath-> + nd_mid)), + ISEQ_TYPE_CLASS); + + COMPILE(ret, "mbase", node->nd_cpath->nd_head); + ADD_INSN (ret, nd_line(node), putnil); /* dummy */ + ADD_INSN3(ret, nd_line(node), defineclass, + ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(2)); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_SCLASS:{ + VALUE iseqval = + NEW_ISEQVAL(node->nd_body, rb_str_new2("singletonclass"), + ISEQ_TYPE_CLASS); + + COMPILE(ret, "sclass#recv", node->nd_recv); + ADD_INSN (ret, nd_line(node), putnil); + ADD_INSN3(ret, nd_line(node), defineclass, + ID2SYM(rb_intern("singletonclass")), iseqval, INT2FIX(1)); + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_COLON2:{ + if (rb_is_const_id(node->nd_mid)) { + /* constant */ + LABEL *lstart = NEW_LABEL(nd_line(node)); + LABEL *lend = NEW_LABEL(nd_line(node)); + DECL_ANCHOR(pref); + DECL_ANCHOR(body); + + compile_colon2(iseq, node, pref, body); + if (LIST_SIZE_ZERO(pref)) { + if (iseq->compile_data->option->inline_const_cache) { + ADD_LABEL(ret, lstart); + ADD_INSN2(ret, nd_line(node), getinlinecache, + NEW_INLINE_CACHE_ENTRY(), lend); + } + else { + ADD_INSN(ret, nd_line(node), putnil); + } + + ADD_SEQ(ret, body); + + if (iseq->compile_data->option->inline_const_cache) { + ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_LABEL(ret, lend); + } + } + else { + ADD_SEQ(ret, pref); + ADD_SEQ(ret, body); + } + } + else { + /* function call */ + ADD_INSN(ret, nd_line(node), putself); + COMPILE(ret, "colon2#nd_head", node->nd_head); + ADD_CALL(ret, nd_line(node), ID2SYM(node->nd_mid), + INT2FIX(1)); + } + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_COLON3:{ + LABEL *lstart = NEW_LABEL(nd_line(node)); + LABEL *lend = NEW_LABEL(nd_line(node)); + debugi("colon3#nd_mid", node->nd_mid); + + /* add cache insn */ + if (iseq->compile_data->option->inline_const_cache) { + ADD_LABEL(ret, lstart); + ADD_INSN2(ret, nd_line(node), getinlinecache, + NEW_INLINE_CACHE_ENTRY(), lend); + ADD_INSN(ret, nd_line(node), pop); + } + + ADD_INSN1(ret, nd_line(node), putobject, rb_cObject); + ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_mid)); + + if (iseq->compile_data->option->inline_const_cache) { + ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_LABEL(ret, lend); + } + + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_CREF:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_CREF")); + break; + } + case NODE_DOT2: + case NODE_DOT3:{ + int flag = type == NODE_DOT2 ? INT2FIX(0) : INT2FIX(1); + COMPILE(ret, "min", (NODE *) node->nd_beg); + COMPILE(ret, "max", (NODE *) node->nd_end); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); + ADD_INSN(ret, nd_line(node), pop); + } + else { + ADD_INSN1(ret, nd_line(node), newrange, flag); + } + break; + } + case NODE_FLIP2: + case NODE_FLIP3:{ + LABEL *lend = NEW_LABEL(nd_line(node)); + LABEL *lfin = NEW_LABEL(nd_line(node)); + LABEL *ltrue = NEW_LABEL(nd_line(node)); + + ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(node->nd_cnt), + INT2FIX(0)); + ADD_INSNL(ret, nd_line(node), branchif, lend) ; + + /* *flip == 0 */ + COMPILE(ret, "flip2 beg", node->nd_beg); + ADD_INSN(ret, nd_line(node), dup); + ADD_INSNL(ret, nd_line(node), branchunless, lfin); + if (nd_type(node) == NODE_FLIP3) { + ADD_INSN(ret, nd_line(node), dup); + ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt)); + ADD_INSNL(ret, nd_line(node), jump, lfin); + } + else { + ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt)); + } + + /* *flip == 1 */ + ADD_LABEL(ret, lend); + COMPILE(ret, "flip2 end", node->nd_end); + ADD_INSNL(ret, nd_line(node), branchunless, ltrue); + ADD_INSN1(ret, nd_line(node), putobject, Qfalse); + ADD_INSN1(ret, nd_line(node), setspecial, INT2FIX(node->nd_cnt)); + + ADD_LABEL(ret, ltrue); + ADD_INSN1(ret, nd_line(node), putobject, Qtrue); + + ADD_LABEL(ret, lfin); + break; + } + case NODE_ATTRSET:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_ATTRSET")); + break; + } + case NODE_SELF:{ + if (!poped) { + ADD_INSN(ret, nd_line(node), putself); + } + + break; + } + case NODE_NIL:{ + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } + break; + } + case NODE_TRUE:{ + if (!poped) { + ADD_INSN1(ret, nd_line(node), putobject, Qtrue); + } + break; + } + case NODE_FALSE:{ + if (!poped) { + ADD_INSN1(ret, nd_line(node), putobject, Qfalse); + } + break; + } + case NODE_ERRINFO:{ + if (!poped) { + if (iseq->type == ISEQ_TYPE_RESCUE) { + ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), + INT2FIX(0)); + } + else { + yarv_iseq_t *ip = iseq; + int level = 0; + while (ip) { + if (ip->type == ISEQ_TYPE_RESCUE) { + break; + } + ip = ip->parent_iseq; + level++; + } + if (ip) { + ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), + INT2FIX(level)); + } + else { + ADD_INSN(ret, nd_line(node), putnil); + } + } + } + break; + } + case NODE_DEFINED:{ + if (!poped) { + LABEL *lfinish = NEW_LABEL(nd_line(node)); + defined_expr(iseq, ret, node->nd_head, lfinish, Qtrue); + ADD_LABEL(ret, lfinish); + } + break; + } + case NODE_POSTEXE:{ + VALUE block = NEW_CHILD_ISEQVAL(node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK); + ADD_INSN1(ret, nd_line(node), postexe, block); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } + break; + } +#ifdef C_ALLOCA + case NODE_ALLOCA:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_ALLOCA")); + break; + } +#endif + case NODE_BMETHOD:{ + /* block method, OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_BMETHOD")); + break; + } + case NODE_MEMO:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_MEMO")); + break; + } + case NODE_IFUNC:{ + /* OK */ + COMPILE_ERROR(("BUG: unknown node: NODE_IFUNC")); + break; + } + case NODE_DSYM:{ + compile_dstr(iseq, ret, node); + if (!poped) { + ADD_SEND(ret, nd_line(node), ID2SYM(idIntern), INT2FIX(0)); + } + else { + ADD_INSN(ret, nd_line(node), pop); + } + break; + } + case NODE_ATTRASGN:{ + DECL_ANCHOR(recv); + DECL_ANCHOR(args); + VALUE flag = 0; + VALUE argc; + + argc = setup_arg(iseq, args, node, &flag); + + if (node->nd_recv == (NODE *) 1) { + ADD_INSN(recv, nd_line(node), putself); + } + else { + COMPILE(recv, "recv", node->nd_recv); + } + + debugp_param("argc", argc); + debugp_param("nd_mid", ID2SYM(node->nd_mid)); + + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + ADD_SEQ(ret, recv); + ADD_SEQ(ret, args); + ADD_INSN1(ret, nd_line(node), setn, INT2FIX(FIX2INT(argc) + 1)); + } + else { + ADD_SEQ(ret, recv); + ADD_SEQ(ret, args); + } + ADD_SEND_R(ret, nd_line(node), ID2SYM(node->nd_mid), argc, 0, INT2FIX(flag)); + ADD_INSN(ret, nd_line(node), pop); + + break; + } + case NODE_OPTBLOCK:{ + /* for optimize */ + LABEL *redo_label = NEW_LABEL(0); + LABEL *next_label = NEW_LABEL(0); + + iseq->compile_data->start_label = next_label; + iseq->compile_data->redo_label = redo_label; + + 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; + } + case NODE_PRELUDE:{ + COMPILE_POPED(ret, "prelude", node->nd_head); + COMPILE_(ret, "body", node->nd_body, poped); + break; + } + default: + COMPILE_ERROR(("BUG: unknown node (default): %s", node_name(type))); + return Qnil; + } + + debug_nodeprint_close(); + return COMPILE_OK; +} + +/***************************/ +/* instruction information */ +/***************************/ + +static int +insn_data_length(INSN *iobj) +{ + return insn_len(iobj->insn_id); +} + +static int +calc_sp_depth(int depth, INSN *insn) +{ + return insn_stack_increase(depth, insn->insn_id, insn->operands); +} + +static int +insn_data_line_no(INSN *iobj) +{ + return insn_len(iobj->line_no); +} + +static VALUE +insn_data_to_s_detail(INSN *iobj) +{ + VALUE str = rb_str_new(0, 0); + char buff[0x100]; + + snprintf(buff, sizeof(buff), "%-16s", insn_name(iobj->insn_id)); + rb_str_cat2(str, buff); + if (iobj->operands) { + char *types = insn_op_types(iobj->insn_id); + int j; + + for (j = 0; types[j]; j++) { + char type = types[j]; + + switch (type) { + case TS_OFFSET: /* label(destination position) */ + { + char buff[0x100]; + LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j); + snprintf(buff, sizeof(buff), "<L%03d>", lobj->label_no); + rb_str_concat(str, rb_str_new2(buff)); + break; + } + break; + case TS_ISEQ: /* iseq */ + { + yarv_iseq_t *iseq = (yarv_iseq_t *)OPERAND_AT(iobj, j); + VALUE val = Qnil; + if (iseq) { + val = iseq->self; + } + rb_str_concat(str, rb_inspect(val)); + } + break; + case TS_LINDEX: + case TS_DINDEX: + case TS_NUM: /* ulong */ + case TS_VALUE: /* VALUE */ + rb_str_concat(str, rb_inspect(OPERAND_AT(iobj, j))); + break; + case TS_ID: /* ID */ + rb_str_concat(str, rb_inspect(OPERAND_AT(iobj, j))); + break; + case TS_GENTRY: + { + struct global_entry *entry = (struct global_entry *) + (OPERAND_AT(iobj, j) & (~1)); + rb_str_cat2(str, rb_id2name(entry->id)); + } + case TS_IC: /* method cache */ + rb_str_cat2(str, "<ic>"); + break; + case TS_CDHASH: /* case/when condition cache */ + rb_str_cat2(str, "<ch>"); + break; + default:{ + rb_bug("unknown operand type: %c", type); + } + } + if (types[j + 1]) { + rb_str_cat2(str, ", "); + } + } + } + return str; +} + +static void +dump_disasm_anchor(LINK_ANCHOR *anc) +{ + dump_disasm_list(FIRST_ELEMENT(anc)); +} + +static void +dump_disasm_list(struct iseq_link_element *link) +{ + int pos = 0; + INSN *iobj; + LABEL *lobj; + VALUE str; + + printf("-- raw disasm--------\n"); + + while (link) { + switch (link->type) { + case ISEQ_ELEMENT_INSN:{ + iobj = (INSN *)link; + str = insn_data_to_s_detail(iobj); + printf("%04d %-65s(%4d)\n", pos, StringValueCStr(str), + insn_data_line_no(iobj)); + pos += insn_data_length(iobj); + break; + } + case ISEQ_ELEMENT_LABEL:{ + lobj = (LABEL *)link; + printf("<L%03d>\n", lobj->label_no); + break; + } + case ISEQ_ELEMENT_NONE:{ + printf("[none]\n"); + break; + } + default: + /* ignore */ + printf("%ld\n", FIX2LONG(link->type)); + rb_bug("dump_disasm_list error"); + } + link = link->next; + } + printf("---------------------\n"); +} + +int +nd_line_debug(NODE * n) +{ + return nd_line(n); +} + +VALUE +insns_name_array(void) +{ + VALUE ary = rb_ary_new(); + int i; + for (i = 0; i < sizeof(insn_name_info) / sizeof(insn_name_info[0]); i++) { + rb_ary_push(ary, rb_str_new2(insn_name_info[i])); + } + return ary; +} + +static LABEL * +register_label(yarv_iseq_t *iseq, struct st_table *labels_table, VALUE obj) +{ + LABEL *label = 0; + obj = rb_convert_type(obj, T_SYMBOL, "Symbol", "to_sym"); + + if (st_lookup(labels_table, obj, (st_data_t *)&label) == 0) { + label = NEW_LABEL(0); + st_insert(labels_table, obj, (st_data_t)label); + } + return label; +} + +static VALUE +get_exception_sym2type(VALUE sym) +{ + static VALUE symRescue, symEnsure, symRetry; + static VALUE symBreak, symRedo, symNext; + + if (symRescue == 0) { + symRescue = ID2SYM(rb_intern("rescue")); + symEnsure = ID2SYM(rb_intern("ensure")); + symRetry = ID2SYM(rb_intern("retry")); + symBreak = ID2SYM(rb_intern("break")); + symRedo = ID2SYM(rb_intern("redo")); + symNext = ID2SYM(rb_intern("next")); + } + + if (sym == symRescue) return CATCH_TYPE_RESCUE; + if (sym == symEnsure) return CATCH_TYPE_ENSURE; + if (sym == symRetry) return CATCH_TYPE_RETRY; + if (sym == symBreak) return CATCH_TYPE_BREAK; + if (sym == symRedo) return CATCH_TYPE_REDO; + if (sym == symNext) return CATCH_TYPE_NEXT; + rb_bug("get_exception_sym2type"); + return 0; +} + +VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt); + +static int +iseq_build_exception(yarv_iseq_t *iseq, struct st_table *labels_table, + VALUE exception) +{ + int i; + VALUE tmp; + + for (i=0; i<RARRAY_LEN(exception); i++) { + VALUE v = rb_ary_entry(exception, i); + VALUE *ptr = RARRAY_PTR(v); + VALUE type = get_exception_sym2type(ptr[0]); + VALUE eiseqval; + LABEL *lstart, *lend, *lcont; + int sp; + + if (ptr[1] == Qnil) { + eiseqval = 0; + } + else { + eiseqval = iseq_load(0, ptr[1], iseq->self, Qnil); + } + + lstart = register_label(iseq, labels_table, ptr[2]); + lend = register_label(iseq, labels_table, ptr[3]); + lcont = register_label(iseq, labels_table, ptr[4]); + sp = NUM2INT(ptr[5]); + + ADD_CATCH_ENTRY(type, lstart, lend, eiseqval, lcont); + } + return COMPILE_OK; +} + + +struct st_table *insn_make_insn_table(void); + +static int +iseq_build_body(yarv_iseq_t *iseq, LINK_ANCHOR *anchor, + VALUE body, VALUE line, struct st_table *labels_table) +{ + /* TODO: body should be freezed */ + VALUE *ptr = RARRAY_PTR(body); + int len = RARRAY_LEN(body); + int i, j; + int line_no = 0; + /* + * index -> LABEL *label + */ + static struct st_table *insn_table; + + if (insn_table == 0) { + insn_table = insn_make_insn_table(); + } + + for (i=0; i<len; i++) { + VALUE obj = ptr[i]; + + if (SYMBOL_P(obj)) { + LABEL *label = register_label(iseq, labels_table, obj); + ADD_LABEL(anchor, label); + } + else if (FIXNUM_P(obj)) { + line_no = NUM2INT(obj); + } + else if (TYPE(obj) == T_ARRAY) { + VALUE *argv = 0; + int argc = RARRAY_LEN(obj) - 1; + VALUE insn_id; + + if (st_lookup(insn_table, rb_ary_entry(obj, 0), &insn_id) == 0) { + // TODO: exception + rb_bug("unknown instruction: "); + } + + if (argc != insn_len(insn_id)-1) { + rb_bug("operand size mismatch"); + } + + if (argc > 0) { + argv = compile_data_alloc(iseq, sizeof(VALUE) * argc); + for (j=0; j<argc; j++) { + VALUE op = rb_ary_entry(obj, j+1); + switch (insn_op_type(insn_id, j)) { + case TS_OFFSET: { + LABEL *label = register_label(iseq, labels_table, op); + argv[j] = (VALUE)label; + break; + } + case TS_LINDEX: + case TS_DINDEX: + case TS_NUM: + argv[j] = (NUM2INT(op), op); + break; + case TS_VALUE: + argv[j] = op; + if (!SPECIAL_CONST_P(op)) { + iseq_add_mark_object(iseq, op); + } + break; + case TS_ISEQ: + { + if (op != Qnil) { + if (TYPE(op) == T_ARRAY) { + argv[j] = + iseq_load(0, op, iseq->self, Qnil); + } + else if (CLASS_OF(op) == cYarvISeq) { + argv[j] = op; + } + else { + /* TODO: exception */ + rb_bug("not an iseq"); + } + iseq_add_mark_object(iseq, argv[j]); + } + else { + argv[j] = 0; + } + } + break; + case TS_GENTRY: + op = rb_convert_type(op, T_SYMBOL, "Symbol", "to_sym"); + argv[j] = (VALUE)rb_global_entry(SYM2ID(op)); + break; + case TS_IC: + argv[j] = (VALUE)NEW_INLINE_CACHE_ENTRY(); + iseq_add_mark_object(iseq, argv[j]); + break; + case TS_ID: + argv[j] = rb_convert_type(op, T_SYMBOL, + "Symbol", "to_sym"); + break; + case TS_CDHASH: + { + int i; + op = rb_convert_type(op, T_ARRAY, "Array", "to_ary"); + for (i=0; i<RARRAY_LEN(op); i+=2) { + VALUE sym = rb_ary_entry(op, i+1); + LABEL *label = + register_label(iseq, labels_table, sym); + rb_ary_store(op, i+1, (VALUE)label | 1); + } + argv[j] = op; + } + break; + default: + rb_bug("unknown operand: %c", insn_op_type(insn_id, j)); + } + } + } + ADD_ELEM(anchor, + (LINK_ELEMENT*)new_insn_core(iseq, line_no, + insn_id, argc, argv)); + } + else { + rb_raise(rb_eTypeError, "unexpected object for instruction"); + } + } + st_free_table(labels_table); + iseq_setup(iseq, anchor); + return COMPILE_OK; +} + +VALUE +iseq_build_from_ary(yarv_iseq_t *iseq, VALUE line, + VALUE locals, VALUE args, VALUE exception, VALUE body) +{ + int i; + int opt = 0; + ID *tbl; + struct st_table *labels_table = st_init_numtable(); + + DECL_ANCHOR(anchor); + + if (iseq->type == ISEQ_TYPE_METHOD || + iseq->type == ISEQ_TYPE_TOP || + iseq->type == ISEQ_TYPE_CLASS) { + opt = 1; + } + + iseq->local_size = opt + RARRAY_LEN(locals); + iseq->local_tbl = (ID *)ALLOC_N(ID *, iseq->local_size); + tbl = iseq->local_tbl + opt; + + for (i=0; i<RARRAY_LEN(locals); i++) { + tbl[i] = SYM2ID(RARRAY_PTR(locals)[i]); + } + + /* args */ + if (FIXNUM_P(args)) { + iseq->argc = FIX2INT(args); + iseq->arg_simple = 1; + } + else { + /* + * [argc, # argc + * opts, # opts + * [label1, label2, ...] # opt labels + * rest_iex, + * block_idx, + * ] + * or + * argc (Fixnum) # arg_simple + */ + int i = 0; + VALUE argc = rb_ary_entry(args, i++); + VALUE arg_opts = rb_ary_entry(args, i++); + VALUE arg_opt_labels = rb_ary_entry(args, i++); + VALUE arg_rest = rb_ary_entry(args, i++); + VALUE arg_block = rb_ary_entry(args, i++); + + iseq->argc = FIX2INT(argc); + iseq->arg_opts = FIX2INT(arg_opts); + iseq->arg_rest = FIX2INT(arg_rest); + iseq->arg_block = FIX2INT(arg_block); + + iseq->arg_opt_tbl = (VALUE *)ALLOC_N(VALUE, iseq->arg_opts); + + for (i=0; i<RARRAY_LEN(arg_opt_labels); i++) { + iseq->arg_opt_tbl[i] = + (VALUE)register_label(iseq, labels_table, + rb_ary_entry(arg_opt_labels, i)); + } + } + + /* exception */ + iseq_build_exception(iseq, labels_table, exception); + + /* body */ + iseq_build_body(iseq, anchor, body, line, labels_table); + return iseq->self; +} diff --git a/compile.h b/compile.h new file mode 100644 index 0000000..2955977 --- /dev/null +++ b/compile.h @@ -0,0 +1,210 @@ +/********************************************************************** + + compile.h - + + $Author$ + $Date$ + created at: 04/01/01 23:36:57 JST + + Copyright (C) 2004-2006 Koichi Sasada + +**********************************************************************/ + +#ifndef _COMPILER_H_INCLUDED_ +#define _COMPILER_H_INCLUDED_ + +#include "version.h" + +#if YARVDEBUG > CPDEBUG +#undef CPDEBUG +#define CPDEBUG YARVDEBUG +#endif + +/* */ +/** + * debug function(macro) interface depend on CPDEBUG + * + * debug level: + * 0: no debug output + * 1: show node type + * 2: show node important parameters + * ... + * 5: show other parameters + * 10: show every AST array + */ + +#if 0 +#undef CPDEBUG +#define CPDEBUG 2 +#endif + +#if CPDEBUG > 0 + +#define debugp(header, value) \ + (debug_indent(0, CPDEBUG, gl_node_level * 2), \ + debug_value(0, CPDEBUG, header, value)) + +#define debugi(header, id) \ + (debug_indent(0, CPDEBUG, gl_node_level * 2), \ + debug_id(0, CPDEBUG, header, id)) + +#define debugp_param(header, value) \ + (debug_indent(1, CPDEBUG, gl_node_level * 2), \ + debug_value(1, CPDEBUG, header, value)) + +#define debugp_verbose(header, value) \ + (debug_indent(2, CPDEBUG, gl_node_level * 2), \ + debug_value(2, CPDEBUG, header, value)) + +#define debugp_verbose_node(header, value) \ + (debug_indent(10, CPDEBUG, gl_node_level * 2), \ + debug_value(10, CPDEBUG, header, value)) + +#define debug_nodeprint(node) \ + debug_indent(-1, CPDEBUG, gl_node_level*2); \ + printf("node: %s (%d)\n", node_name(nd_type(node)), nd_line(node)); \ + gl_node_level ++; + +#define debug_nodeprint_close() gl_node_level --; + +#else + +static inline ID +r_id(ID id) +{ + return id; +} + +static inline VALUE +r_value(VALUE value) +{ + return value; +} + +#define debugi(header, id) r_id(id) +#define debugp(header, value) r_value(value) +#define debugp_verbose(header, value) r_value(value) +#define debugp_verbose_node(header, value) r_value(value) +#define debugp_param(header, value) r_value(value) +#define debug_nodeprint(node) +#define debug_nodeprint_close() +#endif + +#if CPDEBUG > 1 +#define debugs debug_indent(-1, CPDEBUG, gl_node_level*2), printf +#define debug_compile(msg, v) (debug_indent(-1, CPDEBUG, gl_node_level*2), printf("%s", msg), (v)) +#else +#define debugs if(0)printf +#define debug_compile(msg, v) (v) +#endif + + +/* create new label */ +#define NEW_LABEL(l) new_label_body(iseq, l) + +#define iseq_filename(iseq) \ + (((yarv_iseq_t*)DATA_PTR(iseq))->file_name) + +#define NEW_ISEQVAL(node, name, type) \ + new_child_iseq(iseq, node, name, 0, type) + +#define NEW_CHILD_ISEQVAL(node, name, type) \ + new_child_iseq(iseq, node, name, iseq->self, type) + +#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \ + new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym) + +/* add instructions */ +#define ADD_SEQ(seq1, seq2) \ + APPEND_LIST(seq1, seq2) + +/* add an instruction */ +#define ADD_INSN(seq, line, insn) \ + ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, BIN(insn), 0)) + +/* add an instruction with label operand */ +#define ADD_INSNL(seq, line, insn, label) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 1, (VALUE)label)) + +/* add an instruction with some operands (1, 2, 3, 5) */ +#define ADD_INSN1(seq, line, insn, op1) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 1, (VALUE)op1)) + +#define ADD_INSN2(seq, line, insn, op1, op2) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 2, (VALUE)op1, (VALUE)op2)) + +#define ADD_INSN3(seq, line, insn, op1, op2, op3) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_body(iseq, line, BIN(insn), 3, (VALUE)op1, (VALUE)op2, (VALUE)op3)) + +/* Specific Insn factory */ +#define ADD_SEND(seq, line, id, argc) \ + ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(0)) + +#define ADD_CALL(seq, line, id, argc) \ + ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL_BIT)) + +#define ADD_SEND_R(seq, line, id, argc, block, flag) \ + ADD_ELEM(seq, (LINK_ELEMENT *) \ + new_insn_send(iseq, line, \ + (VALUE)id, (VALUE)argc, (VALUE)block, (VALUE)flag)) + +/* add label */ +#define ADD_LABEL(seq, label) \ + ADD_ELEM(seq, (LINK_ELEMENT *)label) + +#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \ + (tmp = rb_ary_new(), \ + rb_ary_push(tmp, type), \ + rb_ary_push(tmp, (VALUE) ls | 1), \ + rb_ary_push(tmp, (VALUE) le | 1), \ + rb_ary_push(tmp, iseqv), \ + rb_ary_push(tmp, (VALUE) lc | 1), \ + rb_ary_push(iseq->compile_data->catch_table_ary, tmp)) + +/* compile node */ +#define COMPILE(anchor, desc, node) \ + (debug_compile("== " desc "\n", \ + iseq_compile_each(iseq, anchor, node, 0))) + +/* compile node, this node's value will be poped */ +#define COMPILE_POPED(anchor, desc, node) \ + (debug_compile("== " desc "\n", \ + iseq_compile_each(iseq, anchor, node, 1))) + +/* compile node, which is poped when 'poped' is true */ +#define COMPILE_(anchor, desc, node, poped) \ + (debug_compile("== " desc "\n", \ + iseq_compile_each(iseq, anchor, node, poped))) + +#define OPERAND_AT(insn, idx) \ + (((INSN*)(insn))->operands[idx]) + +#define INSN_OF(insn) \ + (((INSN*)(insn))->insn_id) + +/* error */ +#define COMPILE_ERROR(strs) \ +{ \ + VALUE tmp = GET_THREAD()->errinfo; \ + if(CPDEBUG)rb_bug strs; \ + GET_THREAD()->errinfo = iseq->compile_data->err_info; \ + rb_compile_error strs; \ + iseq->compile_data->err_info = GET_THREAD()->errinfo; \ + GET_THREAD()->errinfo = tmp; \ + ret = 0; \ + break; \ +} + + +#define COMPILE_OK 1 +#define COMPILE_NG 0 + +#define DECL_ANCHOR(name) \ + LINK_ANCHOR name##_body__ = {{0,}, &name##_body__.anchor}; \ + LINK_ANCHOR *name = & name##_body__ + +#endif // _COMPILER_H_INCLUDED_ diff --git a/configure.in b/configure.in index 1fd0155..be6bbd2 100644 --- a/configure.in +++ b/configure.in @@ -71,6 +71,7 @@ fi if test "$program_prefix" = NONE; then program_prefix= fi + AC_CANONICAL_TARGET target_os=`echo $target_os | sed 's/linux-gnu$/linux/;s/linux-gnu/linux-/'` ac_install_sh='' # unusable for extension libraries. @@ -183,7 +184,7 @@ cygwin*|mingw*) AC_TRY_LINK([#include <stdio.h>], [FILE* volatile f = stdin; return 0;], [rb_cv_msvcrt=`$OBJDUMP -p conftest$ac_exeext | - tr A-Z a-z | + tr A-Z a-z | sed -n '/^[[ ]]*dll name: \(msvc.*\)\.dll$/{s//\1/p;q;}'`], [rb_cv_msvcrt=msvcrt]) test "$rb_cv_msvcrt" = "" && rb_cv_msvcrt=msvcrt]) @@ -345,7 +346,7 @@ AC_ARG_WITH(libc_r, AC_ARG_ENABLE(pthread, [ --enable-pthread use pthread library.], - [enable_pthread=$enableval], [enable_pthread=no]) + [enable_pthread=$enableval], [enable_pthread=yes]) dnl Checks for libraries. case "$target_os" in @@ -831,6 +832,8 @@ if test x"$ac_cv_header_ucontext_h" = xyes; then fi fi +AC_CHECK_FUNCS(backtrace) + dnl default value for $KANJI DEFAULT_KCODE="KCODE_NONE" @@ -1004,11 +1007,11 @@ if test "$with_dln_a_out" != yes; then LDFLAGS='-brtl' XLDFLAGS='-bE:ruby.imp' fi - : ${ARCHFILE="ruby.imp"} + : ${ARCHFILE="ruby.imp"} TRY_LINK='$(CC) $(LDFLAGS) -oconftest $(INCFLAGS) -I$(hdrdir) $(CPPFLAGS)' TRY_LINK="$TRY_LINK"' $(CFLAGS) $(src) $(LIBPATH) $(LOCAL_LIBS) $(LIBS)' - : ${LIBPATHENV=SHLIB_PATH} - rb_cv_dlopen=yes ;; + : ${LIBPATHENV=SHLIB_PATH} + rb_cv_dlopen=yes ;; human*) : ${DLDFLAGS=''} : ${LDSHARED=''} : ${LDFLAGS=''} @@ -1354,7 +1357,7 @@ if test "$enable_shared" = 'yes'; then fi if test "$enable_rpath" = yes; then if test "$GCC" = yes; then - LIBRUBYARG_SHARED='-Wl,-R -Wl,$(libdir) -L$(libdir) -L. '"$LIBRUBYARG_SHARED" + LIBRUBYARG_SHARED='-Wl,-R -Wl,$(libdir) -L$(libdir) -L. '"$LIBRUBYARG_SHARED" else LIBRUBYARG_SHARED='-R $(libdir) -L$(libdir) -L. '"$LIBRUBYARG_SHARED" fi @@ -0,0 +1,71 @@ +/********************************************************************** + + debug.c - + + $Author$ + $Date$ + created at: 04/08/25 02:31:54 JST + + Copyright (C) 2004-2006 Koichi Sasada + +**********************************************************************/ + +#include "ruby.h" + +void +debug_indent(int level, int debug_level, int indent_level) +{ + if (level < debug_level) { + int i; + for (i = 0; i < indent_level; i++) { + fprintf(stderr, " "); + } + fflush(stderr); + } +} + +VALUE +debug_value(int level, int debug_level, char *header, VALUE obj) +{ + if (level < debug_level) { + VALUE str; + str = rb_inspect(obj); + fprintf(stderr, "DBG> %s: %s\n", header, + obj == -1 ? "" : StringValueCStr(str)); + fflush(stderr); + } + return obj; +} + +void +debug_v(VALUE v) +{ + debug_value(0, 1, "", v); +} + +ID +debug_id(int level, int debug_level, char *header, ID id) +{ + if (level < debug_level) { + fprintf(stderr, "DBG> %s: %s\n", header, rb_id2name(id)); + fflush(stderr); + } + return id; +} + +void +gc_check_func(void) +{ + int i; +#define GCMKMAX 0x10 + for (i = 0; i < GCMKMAX; i++) { + rb_ary_new2(1000); + } + rb_gc(); +} + +void +debug_breakpoint(void) +{ + /* */ +} @@ -0,0 +1,47 @@ +/********************************************************************** + + debug.h - YARV Debug function interface + + $Author$ + $Date$ + created at: 04/08/25 02:33:49 JST + + Copyright (C) 2004-2006 Koichi Sasada + +**********************************************************************/ + +#ifndef _DEBUG_H_INCLUDED_ +#define _DEBUG_H_INCLUDED_ + +#include <ruby.h> + +VALUE debug_value(int level, int debug_level, char *header, VALUE v); +ID debug_id(int level, int debug_level, char *header, ID id); +void debug_indent(int level, int debug_level, int indent_level); + +#define dpv(h,v) debug_value(-1, 0, h, v) +#define dp(v) debug_value(-1, 0, "", v) +#define dpi(i) debug_id (-1, 0, "", i) +#define bp() debug_breakpoint() + +void gc_check_func(); + +#if GCDEBUG == 1 + +#define GC_CHECK() \ + gc_check_func() + +#elif GCDEBUG == 2 + +#define GC_CHECK() \ + (printf("** %s:%d gc start\n", __FILE__, __LINE__), \ + gc_check_func(), \ + printf("** end\n")) + +#else + +#define GC_CHECK() + +#endif + +#endif // _DEBUG_H_INCLUDED_ diff --git a/doc/ChangeLog-YARV b/doc/ChangeLog-YARV new file mode 100644 index 0000000..48b00f2 --- /dev/null +++ b/doc/ChangeLog-YARV @@ -0,0 +1,6917 @@ +# $Id: ChangeLog 590 2006-12-31 09:02:34Z ko1 $
+#
+# YARV ChangeLog
+# from Mon, 03 May 2004 01:24:19 +0900
+#
+
+Sun Dec 31 18:01:50 2006 Koichi Sasada <ko1@atdot.net>
+
+ * bin/* : ruby/trunk/bin 11437
+
+
+Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : remove old Kernel#funcall definition
+
+
+2006-12-30(Sat) 07:59:26 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * catch up ruby/trunk 11437
+
+ * eval_intern.h : reorder tag initialization
+
+ * eval.c : fix to support __send!, funcall and prohibit funcall as
+ send
+
+ * eval_error.h, eval_jump.h, eval_safe.h : fix prototypes
+
+ * eval_method.h, vm.c : check re-definition at rb_add_method()
+
+ * yarvcore.h : fix typo
+
+ * compile.c : fix white spaces
+
+ * lib/delegate.rb : fix to support __send, ...
+
+ * lib/getoptlong.rb : fix to work on YARV
+
+ * lib/rss/parser.rb : use __send! instead of __send__
+
+ * sample/test.rb : comment out codes which use |&b| type block parameter
+
+ * ext/ripper/extconf.rb : turn off
+
+ * test/ripper/test_files.rb, test_parser_events.rb,
+ test_scanner_events.rb : fix to check it has ripper module
+
+ * vm_dump.c : remove showing file path length limitation
+
+ * yarvtest/test_eval.rb : use __send! instead of __send__
+
+
+2006-12-19(Tue) 11:46:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * doc/* : added
+
+ * ext/openssl : added
+
+ * ext/ripper : added
+
+ * test/openssl : added
+
+ * test/ripper : added
+
+ * misc : added
+
+ * rb/ -> tool/ : renamed
+
+ * common.mk : fixed for above change
+
+ * ruby_doc/* : move to topdir
+
+ * sample/* : added
+
+ * test2.rb : removed
+
+
+2006-12-15(Fri) 09:42:46 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : remove obsolete codes
+
+ * insns.def : fix a comment of getconstant
+
+
+2006-12-13(Wed) 16:26:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * blockinlining.c, compile.c, compile.h, debug.c, debug.h,
+ insnhelper.h, insns.def, iseq.c, thread.c, thread_pthread.ci,
+ thread_pthread.h, thread_win32.ci, thread_win32.h, vm.c, vm.h,
+ vm_dump.c, vm_evalbody.ci, vm_opts.h.base, yarv.h,
+ yarv_version.h, yarvcore.c, yarvcore.h :
+ add a header includes copyright
+
+
+2006-12-12(Tue) 13:13:32 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb : add PREFETCH() statement
+
+ * vm.h : ditto
+
+ * yarvcore.h : fix LIKELY(x) and
+ remove main_thread_val field from yarv_vm_t
+
+ * yarvcore.c : ditto
+
+ * thread.c : support fork
+
+ * eval_thread.c : ditto
+
+ * process.c : ditto
+
+ * signal.c : ditto
+
+ * test/ruby/test_signal.rb :
+
+ * thread_pthread.ci : rename timer thread functions
+
+ * thread_win32.ci : ditto
+
+
+2006-11-10(Fri) 21:29:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix to compile arguments
+
+ * insns.def : fix to duplicate first array value on concatarray
+ instruction
+
+ * yarvtest/test_bin.rb : add a test for above change
+
+ * sample/test.rb : fix to catch up Ruby HEAD (fix to remove test about
+ module duplicate)
+
+
+2006-11-10(Fri) 12:49:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm_macro.def : fix to inherit visibility on
+ NODE_SUPER method invocation
+
+
+2006-11-10(Fri) 09:13:46 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * class.c : revert module duplicate inclusion
+
+ * parse.y : catch up current Ruby HEAD
+
+ * node.h : ditto
+
+ * compile.c : ditto
+
+ * gc.c : ditto
+
+ * iseq.c : ditto
+
+ * eval_thread.c : define Continuation (null class)
+
+ * vm_dump.c : fix to output backtrae to stderr
+
+ * yarvtest/test_block.rb : remove unsupported test
+
+ * yarvtest/test_class.rb : add a test about super
+
+ * yarvtest/test_syntax.rb : add a test about case/when
+
+
+2006-11-09(Thu) 10:22:59 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * call_cfunc.h -> call_cfunc.ci : renamed
+
+ * vm_evalbody.h, vm_evalbody.ci : ditto
+
+ * thread_pthread.h, thread_pthread.ci : separate declaration and
+ implementation
+
+ * thread_win32.h, thread_win32.ci : ditto
+
+ * thread.c : use *.ci instead of *.c as implementation
+
+ * vm.c : ditto
+
+ * common.mk : fix rules for above changes
+
+
+2006-11-08(Wed) 17:23:23 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm_dump.c : show C level backtrace (pointer only) with
+ backtrace() function (glibc feature)
+
+ * configure.in : ditto
+
+ * yarvcore.c : add NSDR method (show C level backtrace)
+
+ * error.c : fix indent
+
+
+2006-11-07(Tue) 13:17:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c (rb_set_errinfo) : added
+
+ * ruby.h : ditto
+
+ * version.h : fix version number
+
+ * lib/webrick/utils.rb : fix to remove Thread.critical
+
+ * ext/dbm, dl, gdbm, iconv, io, pty, sdbm : added
+
+ * test/dbm, gdbm, io, logger, net, readline, sdbm, soap,
+ webrick, win32ole, wsdl, xsd : added
+
+
+2006-11-06(Mon) 22:32:18 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * array.c : import Ruby HEAD
+
+ * ext/socket/extconf.rb : ditto
+
+ * ext/socket/socket.c : ditto
+
+ * gc.c : ditto
+
+ * lib/date.rb : ditto
+
+ * lib/net/imap.rb : ditto
+
+ * lib/rss/0.9.rb : ditto
+
+ * lib/set.rb : ditto
+
+ * lib/soap/mapping/rubytypeFactory.rb : ditto
+
+ * lib/soap/mimemessage.rb : ditto
+
+ * lib/soap/property.rb : ditto
+
+ * lib/webrick/httprequest.rb : ditto
+
+ * lib/webrick/httputils.rb : ditto
+
+ * lib/xmlrpc/create.rb : ditto
+
+ * lib/xsd/codegen/gensupport.rb : ditto
+
+ * object.c : ditto
+
+ * ruby.h : ditto
+
+ * string.c : ditto
+
+ * version.h : ditto
+
+ * rb/ir.rb : fix to use "diffs" directory
+
+ * vm_dump.c : add "const"
+
+
+2006-11-06(Mon) 16:36:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_proc.c : remove "static" from external global variables
+
+ * eval_thread.c : ditto
+
+ * array.c : fix indent
+
+ * insns.def : add a suitable cast
+
+ * vm_macro.def : allow scalar value on splat arguments
+
+ * yarvtest/test_block.rb : fix to synchronize Ruby HEAD
+
+ * rb/insns2vm.rb : remove String#each for 1.9
+
+ * template/vm.inc.tmpl : ditto (remove String#each_with_index)
+
+
+2006-11-06(Mon) 13:22:34 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * iseq.c : fixed GC debugging outputs
+
+ * rb/parse.rb : fixed output format
+
+
+2006-11-04(Sat) 09:46:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix to duplicate "#{'foo'}" string
+
+ * yarvtest/test_bin.rb : add a test for above
+
+ * ext/readline/readline.c : import Ruby HEAD
+
+ * keywords : ditto
+
+ * lex.c : ditto
+
+ * parse.y : ditto
+
+ * lib/mkmf.rb : ditto
+
+ * test/ruby/test_hash.rb : fix to current specification
+
+ * test/ruby/test_string.rb : ditto
+
+
+2006-11-03(Fri) 20:58:36 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * ext/nkf/nkf-utf8/utf8tbl.h : missed to add
+
+ * configure.in : import ruby HEAD
+
+ * test/ruby/test_array.rb : ditto
+
+ * test/ruby/test_assignment.rb : ditto
+
+ * test/ruby/test_clone.rb : ditto
+
+ * test/socket/test_socket.rb : ditto
+
+ * test/socket/test_unix.rb : ditto
+
+ * test/strscan/test_stringscanner.rb : ditto
+
+ * test/testunit/collector/test_dir.rb : ditto
+
+
+2006-11-03(Fri) 20:22:24 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * array.c : import current ruby HEAD and apply API changes
+ This version has some known bugs
+
+ * bignum.c : ditto
+
+ * blockinlining.c : ditto
+
+ * class.c : ditto
+
+ * compile.c : ditto
+
+ * dir.c : ditto
+
+ * dln.c : ditto
+
+ * enum.c : ditto
+
+ * enumerator.c : ditto
+
+ * error.c : ditto
+
+ * eval.c : ditto
+
+ * eval_error.h : ditto
+
+ * eval_jump.h : ditto
+
+ * eval_load.c : ditto
+
+ * eval_proc.c : ditto
+
+ * ext/*
+
+ * file.c : ditto
+
+ * gc.c : ditto
+
+ * hash.c : ditto
+
+ * insns.def : ditto
+
+ * instruby.rb : ditto
+
+ * intern.h : ditto
+
+ * io.c : ditto
+
+ * iseq.c : ditto
+
+ * lib/*
+
+ * marshal.c : ditto
+
+ * math.c : ditto
+
+ * missing/vsnprintf.c : ditto
+
+ * mkconfig.rb : ditto
+
+ * node.h : ditto
+
+ * numeric.c : ditto
+
+ * object.c : ditto
+
+ * oniguruma.h : ditto
+
+ * pack.c : ditto
+
+ * parse.y : ditto
+
+ * prec.c : ditto
+
+ * process.c : ditto
+
+ * random.c : ditto
+
+ * range.c : ditto
+
+ * rb/ir.rb : ditto
+
+ * re.c : ditto
+
+ * regcomp.c : ditto
+
+ * regerror.c : ditto
+
+ * regexec.c : ditto
+
+ * regint.h : ditto
+
+ * regparse.c : ditto
+
+ * regparse.h : ditto
+
+ * ruby.c : ditto
+
+ * ruby.h : ditto
+
+ * rubytest.rb : ditto
+
+ * runruby.rb : ditto
+
+ * sample/test.rb : ditto
+
+ * signal.c : ditto
+
+ * sprintf.c : ditto
+
+ * st.c : ditto
+
+ * st.h : ditto
+
+ * string.c : ditto
+
+ * struct.c : ditto
+
+ * test/*
+
+ * thread.c : ditto
+
+ * time.c : ditto
+
+ * util.c : ditto
+
+ * variable.c : ditto
+
+ * version.h : ditto
+
+ * vm.c : ditto
+
+ * vm_dump.c : ditto
+
+ * vm_macro.def : ditto
+
+ * win32/*
+
+
+2006-10-31(Tue) 22:47:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * parse.y : fix NEWHEAP bugs (import HEAD)
+
+ * ruby.c, intern.h, yarvcore.c (rb_load_file) : change to
+ return parsed node pointer
+
+ * rb/ir.rb : add check mode
+
+
+2006-09-01(Fri) 22:05:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix a bug of peephole optimization and enable
+ regexp optimization
+
+
+2006-08-21(Mon) 05:27:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/mathn.rb : remove "remove_method :gcd2"
+
+ * opt_insn_unif.def : unset opt setting
+
+ * opt_operand.def : ditto
+
+
+2006-08-18(Fri) 17:55:31 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add dependency of yarvcore.h to thread.o
+
+ * gc.c : change comment line
+
+ * thread.c : remove some line break
+
+ * yarvcore.c : reoder initialize sequence to mark main thread
+
+
+2006-08-18(Fri) 16:51:34 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h : add a support for cache values per thread
+
+ * yarvcore.c : ditto
+
+ * gc.c : ditto
+
+ * thread.c : move a expression after acquiring lock
+
+ * compile.c : add a cast to remove warning
+
+
+2006-08-18(Fri) 02:07:45 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix to return rhs value on ATTRASGIN
+
+ * insns.def (setn) : add insn setn
+
+ * yarvtest/test_bin.rb : add tests for above
+
+
+2006-08-17(Thu) 22:46:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : clear callee_id ([yarv-dev:1073])
+
+
+2006-08-17(Thu) 22:14:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread_pthread.h : fix error message
+
+
+2006-08-17(Thu) 12:23:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : change initilize routine order ([yarv-dev:1067])
+
+ * yarvcore.c (Init_yarv) : init th->machine_stack_start
+
+ * thread_pthread.h : add malloc value check ([yarv-dev:1066])
+
+ * insns.def (opt_eq) : fix typo ([yarv-dev:1072])
+
+ * yarvtest/test_opts.rb : add a test for above
+
+ * yarvtest/test_class.rb : add a test for last commit
+
+
+2006-08-17(Thu) 11:02:16 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * class.c (clone_method) : check undef-ed method ([yarv-dev:1068])
+
+
+2006-08-15(Tue) 15:07:43 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix opt_plus routine ([yarv-dev-en:149])
+
+ * yarvtest/test_opts.rb : add tests for above
+
+
+2006-08-06(Sun) 06:24:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : fix build rule (build only ruby binary when benchmark)
+
+ * yarvcore.[ch] : fix and add yarv_iseq_new_with_* API
+
+ * blockinlining.c : ditto
+
+ * compile.c : ditto
+
+ * compile.h : ditto
+
+ * iseq.c : ditto
+
+ * eval_method.h : check redefinition for specialized instruction
+
+ * insnhelper.h : ditto
+
+ * insns.def : ditto
+
+ * vm.c : ditto
+
+ * vm.h : ditto
+
+ * numeric.c : add Fixnum#succ
+
+ * thread.c : remove duplicated method Thread#current
+
+ * yarvcore.c : remove duplicated method Proc#clone
+
+ * yarvtest/test_opts.rb : added
+
+
+2006-07-20(Thu) 04:10:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix [yarv-dev:1041] problem (raise TypeError)
+
+ * eval.c : rb_funcall2 send as NOEX_PRIVATE and check scope
+
+
+2006-07-20(Thu) 03:38:46 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : fix [yarv-dev:1040] bug
+
+
+2006-07-18(Tue) 18:45:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * some files : set property "svn:eol-style" as native
+
+
+2006-07-18(Tue) 18:35:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * gc.h : fix a static function name
+
+ * vm.c : remove Japanese comments
+
+ * yarvcore.c : add a comment
+
+ * some files : set property "svn:eol-style" as native
+
+
+2006-07-18(Tue) 16:48:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : remove unused code
+
+ * compile.c : add checking value
+
+ * iseq.c : ditto
+
+ * yarvcore.c : fix yarv_th_eval prototype declaration
+
+ * yarvtest/yarvtest.rb : use compile instead of parse method
+
+
+2006-07-12(Wed) 15:18:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarv_version.h : 0.4.1
+
+ * Changes : ditto
+
+
+2006-07-12(Wed) 13:38:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : fix indent
+
+ * gc.h : fix syntax bug
+
+ * thread_pthread.h : vanish warnning message
+
+ * iseq.c : ditto
+
+ * compile.c : ditto
+
+ * thread.c : ditto
+
+ * vm.c : ditto
+
+ * yarvcore.c : prohibit tail call optimization to mark
+ iseq object
+
+ * yarvcore.h : add some allocator function declaration
+
+ * yarvtest/test_eval.rb : remove output
+
+
+2006-07-12(Wed) 05:01:23 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : undef alloc funcs
+
+ * eval_proc.c : ditto (use factory faction)
+
+ * thread.c : ditto
+
+ * vm.c : ditto
+
+ * iseq.c : fix compile option creation
+
+ * rb/allload.rb : use compile_file method
+
+ * rb/compile.rb : ditto
+
+ * rb/parse.rb : ditto
+
+ * template/insnstbl.html : hide mail addr
+
+
+2006-07-11(Tue) 21:34:29 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_dir.rb: new test test_JVN_13947696.
+
+
+2006-07-11(Tue) 21:26:41 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_alias.rb: new test test_JVN_83768862.
+
+
+2006-07-11(Tue) 11:33:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix compile error on C90
+
+
+2006-07-11(Tue) 10:40:23 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * disasm.c : removed
+
+ * iseq.c : added
+
+ * common.mk : ditto
+
+ * blockinlining.c : Get*Val => Get*Ptr
+
+ * eval.c : ditto
+
+ * yarvcore.c : ditto
+
+ * eval_proc.c : ditto
+
+ * vm_dump.c : ditto
+
+ * vm_macro.def : ditto
+
+ * signal.c : ditto
+
+ * vm.c : ditto
+
+ * thread.c : ditto
+
+ * compile.c : rename local variable insnobj => iobj
+
+ * compile.c : support yarv_compile_option_t
+
+ * gc.h : added
+
+ * insns.def : use OPT_CHECKED_RUN instead of IGNORE_OPTIMIZE
+
+ * rb/compile.rb : use compile option
+
+ * template/optinsn.inc.tmpl : fix function name
+
+ * vm_opts.h.base : change macros
+
+ * rb/insns2vm.rb : ditto
+
+ * yarv.h : fix yarvcore_eval_parsed parameter type
+
+ * yarvcore.c : fix some interfaces (functions)
+
+ * yarvcore.h : add a type yarv_compile_option_t
+
+
+2006-07-06(Thu) 13:45:20 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/yasm.rb : pass builder object if block arity == 1
+
+
+2006-07-05(Wed) 11:23:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/yasm.rb : fix method name
+
+ * vm.c (th_set_top_stack) : check toplevel or not
+
+
+2006-07-04(Tue) 20:05:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/compile.rb : added
+
+ * yarvtest/yarvtest.rb : disable load/store test
+
+
+2006-07-04(Tue) 18:17:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix some bugs about load iseq data
+
+ * disasm.c : ditto (store)
+
+ * eval.c (rb_f_local_variables) : fix bugs
+
+ * insns.def : fix otp_ltlt condition bug
+
+ * vm.c : ditto
+
+ * yarvcore.c : rename some functions
+
+ * yarvtest/yarvtest.rb : add iseq load/store tests
+ (to enable this, remove comment)
+
+
+2006-07-03(Mon) 01:54:23 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_thread.c : add parameter "th" to thread_set_raised
+
+ * yarvcore.h : ditto
+
+ * eval_intern.h : ditto
+
+ * eval.c : ditto
+
+ * eval_error.h : declare with ANSI style
+
+ * disasm.c : rename iseq_iseq2simpledata() to iseq_data_to_ary
+
+ * lib/yasm.rb : rename Instruction#to_simpledata to
+ Instruction#to_a
+
+ * yarvcore.c : ditto
+
+ * vm.c : fix bug (Proc.new{|*args| p args}.call(1) #=> 1)
+
+ * yarvtest/test_proc.rb : add a tests for above
+
+
+2006-06-21(Wed) 09:19:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : remove yarv_iseq_t#catch_table_ary and
+ add yarv_iseq_t#compile_data#catch_table_ary
+
+ * compile.h : ditto
+
+ * yarvcore.c : ditto
+
+ * yarvcore.h : ditto
+
+ * eval_thread.c : remove unused code
+
+ * thread.c : add rb_gc_mark_threads() (from eval_thread.c)
+
+
+2006-05-31(Wed) 21:26:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * parse.y : prohibit tail call optimization to mark vparsr
+ object
+
+
+2006-05-25(Thu) 15:37:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * blockinlining.c : support NEW_ATTRASGN node
+
+ * class.c : skip undefined method to collect ([yarv-dev:999])
+
+ * yarvtest/test_class.rb : add a test for above
+
+ * compile.c : fix opt_regexpmatch1 condition
+
+ * lib/monitor.rb : fix [yarv-dev:1009]
+
+ * rb/insns2vm.rb : fix typo
+
+ * thread.c : prohibit unlock by not mutex owner thread
+
+ * vm_opts.h.base : change default option
+
+
+2006-05-18(Thu) 16:00:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * intern.h : fix prototype declarations for last re.c change
+
+
+2006-05-18(Thu) 12:12:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/runruby.rb : added
+
+ * thread.c (rb_thread_alone) : check if vm->living_threads
+ is available
+
+
+2006-05-18(Thu) 12:05:35 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * signal.c : not mask SIGSEGV
+
+ * thread.c : fix debug output on Win32
+
+ * thread.c, thread_pthread.h : add some debug prints
+
+ * yarvcore.c : mark machine registers on thread_mark
+
+
+2006-05-17(Wed) 18:09:20 +900 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (sys_warning): should not call a vararg function
+ rb_sys_warning() indirectly. [ruby-core:07886]
+
+
+2006-05-17(Wed) 16:41:41 +900 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_initialize): should not allow modifying literal
+ regexps. frozen check moved from rb_reg_initialize_m as well.
+
+ * re.c (rb_reg_initialize): should not modify untainted objects in
+ safe levels higher than 3.
+
+ * re.c (rb_memcmp): type change from char* to const void*.
+
+ * dir.c (dir_close): should not close untainted dir stream.
+
+ * dir.c (GetDIR): add tainted/frozen check for each dir operation.
+
+
+2006-05-07(Sun) 21:06:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c : remove Mutex#unlock_and_stop and add Mutex#sleep
+
+ * lib/monitor.rb : ditto
+
+ * lib/thread.rb : ditto
+
+ * thread_pthread.h : fix stack size
+
+ * thread_win32.h : fix sleep
+
+ * yarvcore.h : disable to use get/setcontext
+
+ * lib/webrick/server.rb : add experimental implementation
+ using thraeds pool
+
+
+2006-05-05(Fri) 13:59:00 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/ruby/test_signal.rb : disable a test
+
+ * thread.c : do trylock before lock on mutex_lock
+
+ * thread_win32.h : use CriticalSection instead of Mutex
+
+
+2006-05-05(Fri) 03:03:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : vtune rule make run test.rb
+
+ * disasm.c : fix syntax errors (on VC)
+
+ * yarvcore.c : ditto
+
+ * lib/thread.rb : Mutex#synchronize is defined here
+
+ * lib/*.rb : ditto
+
+ * signal.c : separate pthread or not
+
+ * thread.c : support lightweight wakeup
+
+ * thread_pthread.h : ditto
+
+ * thread_win32.h : ditto
+
+ * yarvcore.h : ditto
+
+ * yarvtest/test_thread.rb : restore last change
+
+
+2006-05-04(Thu) 18:11:43 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_thread.c : remove rb_thread_interrupt
+
+ * intern.h : ditto
+
+ * signal.c : change signal transfer route
+
+ * thread.c : ditto
+
+ * thread_pthread.h : ditto
+
+ * thread_win32.h : ditto
+
+ * yarv.h : support GET_VM()
+
+ * yarvcore.h : change yarv_thread_t/yarv_vm_t structure
+
+ * yarvtest/test_thread.rb : decrease threads to test
+
+
+2006-05-04(Thu) 00:26:18 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread_pthread.h : experimental support of thread cache
+
+
+2006-04-25(Tue) 22:30:14 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h : remove struct yarv_cmethod_info, add
+ data structure for profiling and extend yarv_control_frame_t
+
+ * vm.c : make pop_frame() and apply above change
+
+ * eval.c : ditto
+
+ * vm_dump.c : ditto
+
+ * vm_macro.def : ditto
+
+ * insns.def (leave): use pop_frame() instead of
+ POP_CONTROL_STACK_FRAME() macro
+
+ * insnhelper.h : remove some macros
+
+ * yarvcore.c : change th_set_top_stack() prototype
+
+
+2006-04-18(Tue) 18:37:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, disasm.c : support export/import exception
+ information
+
+ * yarvcore.h : change "struct catch_table_entry" member variable
+ order
+
+
+2006-04-13(Thu) 17:11:30 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * bignum.c : import ruby 1.9 HEAD (Ruby 1.9.0 2006-04-08)
+
+ * dir.c : ditto
+
+ * enumerator.c : ditto
+
+ * ext/.document : ditto
+
+ * ext/extmk.rb : ditto
+
+ * ext/nkf/lib/kconv.rb : ditto
+
+ * ext/nkf/nkf-utf8/nkf.c : ditto
+
+ * ext/nkf/nkf-utf8/utf8tbl.c : ditto
+
+ * ext/nkf/nkf.c : ditto
+
+ * ext/nkf/test.rb : ditto
+
+ * ext/socket/.cvsignore : ditto
+
+ * ext/win32ole/sample/excel2.rb : ditto
+
+ * ext/win32ole/tests/testOLEMETHOD.rb : ditto
+
+ * ext/win32ole/tests/testOLEPARAM.rb : ditto
+
+ * ext/win32ole/tests/testOLETYPE.rb : ditto
+
+ * ext/win32ole/tests/testOLETYPELIB.rb : ditto
+
+ * ext/win32ole/tests/testOLEVARIABLE.rb : ditto
+
+ * ext/win32ole/tests/testOLEVARIANT.rb : ditto
+
+ * ext/win32ole/tests/testWIN32OLE.rb : ditto
+
+ * ext/win32ole/tests/testall.rb : ditto
+
+ * ext/win32ole/win32ole.c : ditto
+
+ * gc.c : ditto
+
+ * instruby.rb : ditto
+
+ * io.c : ditto
+
+ * lib/delegate.rb : ditto
+
+ * lib/fileutils.rb : ditto
+
+ * lib/find.rb : ditto
+
+ * lib/irb/ruby-lex.rb : ditto
+
+ * lib/mkmf.rb : ditto
+
+ * lib/net/http.rb : ditto
+
+ * lib/open-uri.rb : ditto
+
+ * lib/pathname.rb : ditto
+
+ * lib/rational.rb : ditto
+
+ * lib/rdoc/parsers/parse_rb.rb : ditto
+
+ * lib/rdoc/ri/ri_paths.rb : ditto
+
+ * lib/resolv.rb : ditto
+
+ * lib/test/unit/collector/objectspace.rb : ditto
+
+ * lib/webrick/httpservlet/cgihandler.rb : ditto
+
+ * math.c : ditto
+
+ * mkconfig.rb : ditto
+
+ * object.c : ditto
+
+ * oniguruma.h : ditto
+
+ * pack.c : ditto
+
+ * parse.y : ditto
+
+ * re.c : ditto
+
+ * re.h : ditto
+
+ * regcomp.c : ditto
+
+ * regerror.c : ditto
+
+ * regparse.c : ditto
+
+ * ruby.h : ditto
+
+ * rubytest.rb : ditto
+
+ * runruby.rb : ditto
+
+ * string.c : ditto
+
+ * test/digest/test_digest.rb : ditto
+
+ * test/pathname/test_pathname.rb : ditto
+
+ * test/ruby/envutil.rb : ditto
+
+ * test/ruby/test_float.rb : ditto
+
+ * test/ruby/test_pack.rb : ditto
+
+ * time.c : ditto
+
+ * util.c : ditto
+
+ * version.h : ditto
+
+ * win32/mkexports.rb : ditto
+
+ * win32/resource.rb : ditto
+
+ * win32/win32.c : ditto
+
+
+2006-04-11(Tue) 11:26:53 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/yasm.rb : move to lib/yasm.rb
+
+
+2006-04-09(Sun) 03:04:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : change to accept method iseq object when loading from
+ simple data
+
+ * yarvcore.c : add a debug output
+
+ * rb/yasm.rb : change some interfaces
+
+
+2006-04-07(Fri) 20:25:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix miss about range of catch "next"
+
+ * eval.c : add braces
+
+
+2006-04-07(Fri) 11:09:43 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : fix some make rules
+
+ * insns.def : rename some instructions name
+
+ * rb/insns2vm.rb : change some operand type name
+
+ * vm_evalbody.h : ditto
+
+ * template/insns.inc.tmpl : add YARV_MAX_INSTRUCTION_SIZE macro
+
+ * compile.c, disasm.c, yarvcore.c : support load/store iseq from/to simple
+ data structure such as array, literals, and so on
+
+ * rb/yasm.rb : supported
+
+ * vm.c : change interface of eval_define_method
+
+ * yarvcore.h : remove unused externals
+
+
+2006-03-08(Wed) 10:31:29 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/delegate.rb (DelegateClass): do not delegate #send and
+ #funcall.
+
+
+2006-02-27(Mon) 22:39:17 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/thread.rb: last commit causes busy loop, revert it. [yarv-dev:990]
+
+ * lib/thread.rb: non_block=true wrongly caused ThreadError.
+
+
+2006-02-27(Mon) 21:33:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : fix to display command line
+
+ * compile.c : fix comparison between a pointer and 0
+
+ * debug.c : fix to output stder
+
+ * disasm.c : add debug function
+
+ * vm_dump.c : ditto
+
+ * eval_proc.c : fix to skip class definition
+
+ * ruby.h : fix T_VALUE to T_VALUES
+
+ * gc.c : ditto
+
+ * node.h : fix prototypes
+
+ * vm.c : add VM_DEBUG macro
+
+ * vm.c : fix compile error on VC++
+
+ * vm.c : fix to inherit last lfp[0] on th_set_finish_env
+
+ * vm.c : fix to add one svar location for any frame
+
+ * vm_macro.def : ditto
+
+ * yarvcore.h : add YARV_CLASS_SPECIAL_P() and YARV_BLOCK_PTR_P()
+
+ * rdoc/ : removed
+
+ * insns.def : fix to propagete throw state
+
+
+2006-02-27(Mon) 13:54:47 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * ext/syslog: imported from Ruby CVS trunk HEAD.
+
+ * ext/racc: ditto.
+
+
+2006-02-27(Mon) 12:47:10 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * parse.y: follow coding style change.
+
+
+2006-02-27(Mon) 11:53:07 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/README: imported from Ruby CVS trunk HEAD.
+
+ * lib/gserver.rb: ditto.
+
+ * lib/readbytes.rb: ditto.
+
+ * lib/parsearg.rb: ditto.
+
+ * lib/racc: ditto.
+
+ * lib/rinda: ditto.
+
+
+2006-02-27(Mon) 11:27:19 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/thread.rb (Queue#pop): faster code. [yarv-dev:973]
+
+ * lib/thread.rb (Queue#pop): avoid to push same thread in to
+ @waiting.
+
+
+2006-02-23(Thu) 23:32:53 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/open3.rb: imported from Ruby CVS trunk HEAD (rev 1.12).
+
+
+2006-02-23(Thu) 15:10:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : support rb_frame_self()
+
+ * eval_intern.h (th_get_ruby_level_cfp) : return 0 if no cfp
+
+ * eval_load.c : comment out scope set
+
+ * yarvcore.c : fix to initialize/free process of iseq
+
+ * vm.c (th_invoke_proc) : fix to set special cref always
+
+ * yarvtest/test_proc.rb : add a test for above
+
+
+2006-02-22(Wed) 23:33:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add rule "runruby"
+
+ * eval_thread.c : remove obsolete comment
+
+ * eval.c : remove unused functions
+
+ * signal.c : ditto
+
+ * gc.c : add rb_register_mark_object() and use it
+
+ * eval_load.c : ditto
+
+ * eval_proc.c : ditto
+
+ * ext/etc/etc.c : ditto
+
+ * ext/win32ole/win32ole.c : ditto
+
+ * ruby.h : ditto
+
+ * yarvcore.h : ditto
+
+ * thread.c : add rb_thread_run_parallel()
+
+ * yarvcore.c : change bootstrap
+
+
+2006-02-22(Wed) 19:27:33 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * ext/win32ole/.cvsignore : removed
+
+ * ext/win32ole/.document : ditto
+
+
+2006-02-22(Wed) 18:17:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : set Binding as YARVCore::VM::Binding
+
+
+2006-02-22(Wed) 12:54:45 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * ChangeLog : remove needless line
+
+
+2006-02-22(Wed) 12:49:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rubysig.h : remove CHECK_INTS
+
+ * eval.c : ditto
+
+ * eval_load.c : ditto
+
+ * ext/readline/readline.c : ditto
+
+ * thread.c : ditto
+
+ * win32/win32.c : ditto
+
+ * yarv_version.h : 0.4.0
+
+ * Changes : ditto
+
+
+2006-02-22(Wed) 11:36:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test.rb : removed
+
+
+2006-02-22(Wed) 11:12:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * README : renewed
+
+ * version.c : fixed version message
+
+ * yarvext/ : removed
+
+
+2006-02-22(Wed) 10:33:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/.document : imported from Ruby 1.9 HEAD
+
+ * .document : ditto
+
+ * ext/.document : ditto
+
+ * lib/ftools.rb : ditto
+
+ * lib/rdoc/ : ditto
+
+ * eval_thread.c : remove unused functions
+
+ * process.c : ditto
+
+ * rb/insns2vm.rb : compare modified date of vm_opts.h and
+ vm_opts.h.base
+
+ * ruby.h : rename RValue to RValues
+
+ * gc.c : ditto
+
+ * vm.c : ditto
+
+
+2006-02-22(Wed) 06:32:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * configure.in : remove last commit
+
+
+2006-02-22(Wed) 06:18:53 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * configure.in : add default program prefix "-yarv"
+
+
+2006-02-22(Wed) 06:11:36 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : change default rule (same as HEAD)
+
+ * configure : removed
+
+ * eval.c : remove last commit
+
+ * vm.c : fix stack traverse
+
+ * yarvcore.c : initialize top of control frame
+
+ * version.c : 2.0
+
+ * version.h : ditto
+
+
+2006-02-22(Wed) 04:50:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : change to rewind C level control frame
+
+ * vm.c : change to initialize cfp#proc and fix comparison of
+ cfp and limit_cfp
+
+ * yarvcore.c : remove last commit
+
+
+2006-02-22(Wed) 03:25:56 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : initialize each stack of thread
+
+
+2006-02-22(Wed) 00:02:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c : fix synchornize return value ([yarv-dev:957])
+ and some synchornization error
+
+ * thread_pthread.h : add debug helper function
+
+
+2006-02-21(Tue) 20:54:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : fix place of rb_thread_terminate_all()
+
+ * eval_thread.c : remove unused functions
+
+ * yarv.h : remove GET_VM()
+
+ * eval_jump.h : ditto
+
+ * insns.def : ditto
+
+ * vm_dump.c :
+
+ * intern.h : change rb_thread_signal_raise/exit interface
+
+ * signal.c : ditto
+
+ * thread.c : ditto
+
+ * test/ruby/test_beginendblock.rb : use block with IO.popen
+
+ * thread_pthread.h : fix interrupt process
+
+ * thread_win32.h : ditto
+
+ * yarvcore.c : fix thread free process
+
+ * yarvcore.h : remove yarv_vm_t#thread_critical, etc
+
+
+2006-02-21(Tue) 12:42:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_thread.c : remove unused function rb_thread_schedule()
+
+ * thread.c : rename yarv_thread_schedule to rb_thread_schedule()
+
+ * thread.c, eval.c : fix to terminate all thread and barrier at
+ eval.c#ruby_cleanup()
+
+ * thread_win32.h : remove native_thread_cleanup()
+
+ * thread_pthread.h : ditto
+
+ * yarvcore.c : ditto
+
+ * yarvtest/test_thread.rb : separete assersions to tests
+
+
+2006-02-21(Tue) 02:13:33 +900 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (f_arglist): should set command_start = Qtrue for
+ command body. [ruby-talk:180648]
+
+
+2006-02-20(Mon) 20:41:07 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c : fix to synchronize signal_thread_list access
+ and fix typo
+
+
+2006-02-20(Mon) 17:54:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_proc.c : remove unused Binding functions and
+ set is_lambda of Proc used define_method
+
+ * yarvcore.c : support Proc#dup/clone, Binding#dup/clone
+
+ * sample/test.rb : remove unsupport features (Proc as Binding)
+
+
+2006-02-20(Mon) 16:28:59 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add a dependency to vm.c on eval_intern.h
+
+ * eval_intern.h : fix to initialize tag->tag
+
+ * yarvtest/test_jump.rb : add tests for above
+
+ * eval_jump.h : use local variable
+
+
+2006-02-20(Mon) 15:13:24 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bm_vm3_thread_create_join.rb : added
+
+ * test/yaml/test_yaml.rb : imported from Ruby CVS trunk HEAD
+
+
+2006-02-20(Mon) 14:49:46 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/yaml.rb: imported from Ruby CVS trunk HEAD.
+
+ * lib/yaml: ditto.
+
+ * ext/syck: ditto.
+
+
+2006-02-20(Mon) 13:58:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support block parameter which is NODE_ATTRASGN
+
+ * yarvtest/test_block.rb : add tests for above
+
+ * compile.c : fix NODE_DASGN_CURR level check
+
+ * compile.c : fix "||=" (at firtst, check "defined? val")
+
+ * compile.c : fix NODE_MATCH3 (permute receiver and argument)
+
+ * yarvtest/test_bin.rb : add tests for above
+
+ * eval.c : add rb_each()
+
+ * test/ruby/test_signal.rb : increment a timeout value
+
+ * thread.c, yarvcore.h : fix "join" flow
+
+ * thread_pthread.h : ditto
+
+ * thread_win32.h : ditto
+
+ * yarvtest/test_thread.rb : add a test for above
+
+ * vm.h, vm.c, vm_dump.c, insns.def : add FRAME_MAGIC_LAMBDA and
+ support return from lambda (especially retrun from method defined
+ by "define_method")
+
+ * yarvtest/test_method.rb : add a test for above
+
+ * yarvcore.c : remove unused functions
+
+
+2006-02-20(Mon) 11:22:31 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_eval.rb: now Object#funcall is defined.
+
+
+2006-02-20(Mon) 11:04:32 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/irb/lc/ja/CVS: removed.
+
+
+2006-02-20(Mon) 10:55:59 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/mutex_m.rb: imported from Ruby CVS trunk HEAD.
+
+ * lib/observer.rb: ditto.
+
+ * lib/wsdl: ditto.
+
+ * lib/monitor.rb: ditto (removing Thread.critical=).
+
+ * lib/xsd: ditto.
+
+ * lib/soap: ditto.
+
+ * lib/drb.rb: ditto.
+
+ * lib/drb: ditto.
+
+
+2006-02-20(Mon) 10:49:31 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * yarvcore.c (Init_yarvcore): fix typo (duo -> dup).
+
+
+2006-02-19(Sun) 01:27:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : "return" from lambda{} break block
+
+ * eval.c : Unsupport Proc as Binding
+
+ * test/ruby/test_eval.rb : apply above changes
+
+ * yarvcore.c : remove unused function yarv_yield_values()
+
+
+2006-02-18(Sat) 03:19:36 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c, insns.def : fix passing value when thread killed
+
+ * yarvtest/test_thread.rb : add tests for above
+
+
+2006-02-19(Sun) 01:19:42 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/thread.rb (SizedQueue): didn't work. This patch was
+ contributed by yukimizake. [yarv-dev:916]
+
+
+2006-02-18(Sat) 03:19:36 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c, insns.def : fix passing value when thread killed
+
+ * yarvtest/test_thread.rb : add tests for above
+
+
+2006-02-18(Sat) 02:40:18 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, vm.c, vm_macro.def : change BMETHOD algorithm
+ ([yarv-dev:914])
+
+ * yarvtest/test_class.rb : add a test for above
+
+
+2006-02-17(Fri) 23:59:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, yarv.h : change th_invoke_proc() interface
+
+ * eval_proc.c : ditto
+
+ * signal.c : ditto
+
+ * thread.c : ditto
+
+ * yarvcore.c : ditto
+
+ * vm_macro.def : ditto and fix NODE_BMETHOD call
+
+ * vm.c : change name ("th_set_env()" to "push_frame()") and
+ change interface
+
+ * insns.def : ditto
+
+ * eval.c : remove proc_jump_error()
+
+ * benchmark/bm_app_answer.rb : added
+
+ * vm_opts.h.base : add optimize option
+
+
+2006-02-17(Fri) 13:37:57 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c, ruby.h : add rb_errinfo()
+
+ * eval_error.h (error_pos) : fix process order
+
+ * bin/erb : imported from ruby 1.9
+
+ * bin/irb : ditto
+
+ * bin/rdoc : ditto
+
+ * bin/ri : ditto
+
+ * bin/testrb : ditto
+
+ * ext/curses/.cvsignore : ditto
+
+ * ext/curses/curses.c : ditto
+
+ * ext/curses/depend : ditto
+
+ * ext/curses/extconf.rb : ditto
+
+ * ext/curses/hello.rb : ditto
+
+ * ext/curses/mouse.rb : ditto
+
+ * ext/curses/rain.rb : ditto
+
+ * ext/curses/view.rb : ditto
+
+ * ext/curses/view2.rb : ditto
+
+ * ext/fcntl/.cvsignore : ditto
+
+ * ext/fcntl/depend : ditto
+
+ * ext/fcntl/extconf.rb : ditto
+
+ * ext/fcntl/fcntl.c : ditto
+
+ * ext/readline/README : ditto
+
+ * ext/readline/README.ja : ditto
+
+ * ext/readline/depend : ditto
+
+ * ext/readline/extconf.rb : ditto
+
+ * ext/readline/readline.c : ditto
+
+ * ext/win32ole/.document : ditto
+
+ * ext/zlib/doc/zlib.rd : ditto
+
+ * ext/zlib/extconf.rb : ditto
+
+ * ext/zlib/zlib.c : ditto
+
+ * lib/cgi/.document : ditto
+
+ * lib/cgi/session.rb : ditto
+
+ * lib/cgi/session/pstore.rb : ditto
+
+ * lib/shell/builtin-command.rb : ditto
+
+ * lib/shell/command-processor.rb : ditto
+
+ * lib/shell/error.rb : ditto
+
+ * lib/shell/filter.rb : ditto
+
+ * lib/shell/process-controller.rb : ditto
+
+ * lib/shell/system-command.rb : ditto
+
+ * lib/shell/version.rb : ditto
+
+ * lib/xmlrpc/.document : ditto
+
+ * lib/xmlrpc/README.rdoc : ditto
+
+ * lib/xmlrpc/README.txt : ditto
+
+ * lib/xmlrpc/base64.rb : ditto
+
+ * lib/xmlrpc/client.rb : ditto
+
+ * lib/xmlrpc/config.rb : ditto
+
+ * lib/xmlrpc/create.rb : ditto
+
+ * lib/xmlrpc/datetime.rb : ditto
+
+ * lib/xmlrpc/httpserver.rb : ditto
+
+ * lib/xmlrpc/marshal.rb : ditto
+
+ * lib/xmlrpc/parser.rb : ditto
+
+ * lib/xmlrpc/server.rb : ditto
+
+ * lib/xmlrpc/utils.rb : ditto
+
+ * rdoc/README : ditto
+
+ * rdoc/code_objects.rb : ditto
+
+ * rdoc/diagram.rb : ditto
+
+ * rdoc/dot/dot.rb : ditto
+
+ * rdoc/generators/chm_generator.rb : ditto
+
+ * rdoc/generators/html_generator.rb : ditto
+
+ * rdoc/generators/ri_generator.rb : ditto
+
+ * rdoc/generators/template/chm/chm.rb : ditto
+
+ * rdoc/generators/template/html/hefss.rb : ditto
+
+ * rdoc/generators/template/html/html.rb : ditto
+
+ * rdoc/generators/template/html/kilmer.rb : ditto
+
+ * rdoc/generators/template/html/old_html.rb : ditto
+
+ * rdoc/generators/template/html/one_page_html.rb : ditto
+
+ * rdoc/generators/template/xml/rdf.rb : ditto
+
+ * rdoc/generators/template/xml/xml.rb : ditto
+
+ * rdoc/generators/xml_generator.rb : ditto
+
+ * rdoc/markup/sample/rdoc2latex.rb : ditto
+
+ * rdoc/markup/sample/sample.rb : ditto
+
+ * rdoc/markup/simple_markup.rb : ditto
+
+ * rdoc/markup/simple_markup/fragments.rb : ditto
+
+ * rdoc/markup/simple_markup/inline.rb : ditto
+
+ * rdoc/markup/simple_markup/lines.rb : ditto
+
+ * rdoc/markup/simple_markup/preprocess.rb : ditto
+
+ * rdoc/markup/simple_markup/to_flow.rb : ditto
+
+ * rdoc/markup/simple_markup/to_html.rb : ditto
+
+ * rdoc/markup/simple_markup/to_latex.rb : ditto
+
+ * rdoc/markup/test/AllTests.rb : ditto
+
+ * rdoc/markup/test/TestInline.rb : ditto
+
+ * rdoc/markup/test/TestParse.rb : ditto
+
+ * rdoc/options.rb : ditto
+
+ * rdoc/parsers/parse_c.rb : ditto
+
+ * rdoc/parsers/parse_f95.rb : ditto
+
+ * rdoc/parsers/parse_rb.rb : ditto
+
+ * rdoc/parsers/parse_simple.rb : ditto
+
+ * rdoc/parsers/parserfactory.rb : ditto
+
+ * rdoc/rdoc.rb : ditto
+
+ * rdoc/ri/ri_cache.rb : ditto
+
+ * rdoc/ri/ri_descriptions.rb : ditto
+
+ * rdoc/ri/ri_display.rb : ditto
+
+ * rdoc/ri/ri_driver.rb : ditto
+
+ * rdoc/ri/ri_formatter.rb : ditto
+
+ * rdoc/ri/ri_options.rb : ditto
+
+ * rdoc/ri/ri_paths.rb : ditto
+
+ * rdoc/ri/ri_reader.rb : ditto
+
+ * rdoc/ri/ri_util.rb : ditto
+
+ * rdoc/ri/ri_writer.rb : ditto
+
+ * rdoc/template.rb : ditto
+
+ * rdoc/tokenstream.rb : ditto
+
+ * rdoc/usage.rb : ditto
+
+ * test/xmlrpc/data/bug_bool.expected : ditto
+
+ * test/xmlrpc/data/bug_bool.xml : ditto
+
+ * test/xmlrpc/data/bug_cdata.expected : ditto
+
+ * test/xmlrpc/data/bug_cdata.xml : ditto
+
+ * test/xmlrpc/data/bug_covert.expected : ditto
+
+ * test/xmlrpc/data/bug_covert.xml : ditto
+
+ * test/xmlrpc/data/datetime_iso8601.xml : ditto
+
+ * test/xmlrpc/data/fault.xml : ditto
+
+ * test/xmlrpc/data/value.expected : ditto
+
+ * test/xmlrpc/data/value.xml : ditto
+
+ * test/xmlrpc/data/xml1.expected : ditto
+
+ * test/xmlrpc/data/xml1.xml : ditto
+
+ * test/xmlrpc/test_datetime.rb : ditto
+
+ * test/xmlrpc/test_features.rb : ditto
+
+ * test/xmlrpc/test_marshal.rb : ditto
+
+ * test/xmlrpc/test_parser.rb : ditto
+
+ * test/xmlrpc/test_webrick_server.rb : ditto
+
+ * test/xmlrpc/webrick_testing.rb : ditto
+
+ * test/zlib/test_zlib.rb : ditto
+
+
+2006-02-17(Fri) 09:41:35 +900 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * thread.c (sleep_timeval): sleep should always sleep for
+ specified amount of time. [ruby-talk:180067]
+
+
+2006-02-17(Fri) 02:20:32 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_safe.h, ruby.h : remove ruby_safe_level and add
+ rb_safe_level() and rb_set_safe_level_force()
+
+ * eval.c : use above functions
+
+ * eval_jump.h : ditto
+
+ * eval_load.c : ditto
+
+ * eval_method.h : ditto
+
+ * eval_proc.c : ditto
+
+ * eval_thread.c : ditto
+
+ * gc.c : ditto
+
+ * signal.c : ditto
+
+ * variable.c : ditto
+
+ * ext/win32ole/win32ole.c : ditto
+
+ * vm.c (th_invoke_proc) : save and restore safe level
+
+ * yarvtest/test_proc.rb : add tests for above
+
+ * thread.c : remove unused functions
+
+
+2006-02-17(Fri) 01:08:23 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : remove a setspecial second unused operand
+
+ * eval_load.c : remove unused variable th
+
+ * eval_proc.c, yarvcore.c : remove some functions from eval_proc.c
+ and move to yarvcore.c
+
+ * insns.def : fix to delete warnings
+
+ * sample/test.rb : comment out Proc#clone tests
+
+ * version.c : add constant RUBY_VM_DATE
+
+ * vm.c : fix some functions
+
+
+2006-02-16(Thu) 22:58:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, vm.c : use th_yield_setup_args at yield and Proc#call
+
+
+2006-02-16(Thu) 19:51:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix analysis of block parameter
+
+ * disasm.c : remove rb_bug() (temporarily)
+
+ * insns.def, vm.c : fix passing block parameter
+
+ * sample/test.rb : add "Proc = YARVCore::VM::Proc"
+
+ * test/ruby/test_readpartial.rb : disable on mswin32
+
+ * test/socket/test_tcp.rb : ditto
+
+ * thread.c : fix syntax error (for non GCC)
+
+
+2006-02-15(Wed) 22:34:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_method.h : move rb_clear_cache_by_id position
+
+ * thread.c : fix Thread#kill
+
+ * test/ruby/test_readpartial.rb : enable tests except cygwin version
+
+ * test/ruby/test_signal.rb : ditto and enable timeout
+
+
+2006-02-15(Wed) 22:13:29 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/runit: forgot to commit.
+
+
+2006-02-15(Wed) 22:12:25 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/weakref.rb: do not use Thread.critical=.
+
+ * lib/singleton.rb: ditto.
+
+ * lib/timeout.rb: ditto.
+
+ * lib/thread.rb: ditto.
+
+ * test/inlinetest.rb: forgot to commit.
+
+
+2006-02-15(Wed) 21:34:17 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/test_pp.rb: imported from Ruby CVS trunk HEAD.
+
+ * test/test_shellwords.rb: ditto.
+
+ * test/test_set.rb: ditto.
+
+ * test/test_time.rb: ditto.
+
+ * test/test_ipaddr.rb: ditto.
+
+ * test/test_prettyprint.rb: ditto.
+
+ * test/test_tsort.rb: ditto.
+
+ * test/strscan: ditto.
+
+ * test/testunit: ditto.
+
+
+2006-02-15(Wed) 20:03:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_method.h : duplicate NODE_METHOD at make an alias
+
+ * yarvtest/test_method.rb : add a test for above
+
+
+2006-02-15(Wed) 19:48:59 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/rss: imported from Ruby CVS trunk HEAD.
+
+
+2006-02-15(Wed) 19:47:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, compile.c, vm.c : remove methoddef, singletonmethoddef
+ instructions and make new insn definemethod
+
+ * yarvcore.c : set toplevel visibility to private
+
+
+2006-02-15(Wed) 17:39:16 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_intern.h :
+
+ * eval_jump.h, vm.c : localjump_error() and jump_tag_but_local_jump()
+ move to th_localjump_error and th_jump_tag_but_local_jump at vm.c
+
+ * eval.c : ditto
+
+ * eval_load.c : ditto
+
+ * insns.def : ditto
+
+ * vm.c : ditto
+
+ * vm.c (th_make_jump_tag_but_local_jump) : added
+
+ * opt_insn_unif.def : fix indnet (revert change)
+
+ * opt_operand.def : ditto
+
+ * rb/insns2vm.rb : fix error message
+
+ * thread.c : raise exception at join if illegal local jump
+
+
+2006-02-15(Wed) 14:21:45 +900 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ChangeLog: add local variables line to support Emacs.
+
+ * eval.c (rb_obj_instance_exec): add new method from 1.9.
+
+ * eval.c (rb_mod_module_exec): ditto.
+
+ * eval.c (yield_under_i): should not pass self as an argument to
+ the block for instance_eval. [ruby-core:07364]
+
+ * eval.c (rb_obj_instance_eval): should be no singleton classes for
+ true, false, and nil. [ruby-dev:28186]
+
+
+2006-02-14(Tue) 19:30:20 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * array.c : fix indent
+
+ * eval.c : fix block_given
+
+ * gc.c : add STACK_START and use it as a substitute for
+ rb_gc_stack_start
+
+ * vm.c : fix to raise error if th_yield doesn't have block given
+
+ * yarvcore.c : fix to skip iseq mark array at ObjectSpace.each_object
+
+
+2006-02-14(Tue) 18:15:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * configure.in : enable pthread by deafult
+
+ * ascii.c : import ruby 1.9 HEAD
+
+ * bignum.c : ditto
+
+ * compar.c : ditto
+
+ * configure : ditto
+
+ * defines.h : ditto
+
+ * dln.c : ditto
+
+ * dln.h : ditto
+
+ * enum.c : ditto
+
+ * enumerator.c : ditto
+
+ * euc_jp.c : ditto
+
+ * ext/win32ole/tests/testWIN32OLE.rb : ditto
+
+ * ext/win32ole/win32ole.c : ditto
+
+ * file.c : ditto
+
+ * hash.c : ditto
+
+ * io.c : ditto
+
+ * lex.c : ditto
+
+ * lib/irb/init.rb : ditto
+
+ * lib/rexml/document.rb : ditto
+
+ * main.c : ditto
+
+ * marshal.c : ditto
+
+ * math.c : ditto
+
+ * missing.h : ditto
+
+ * object.c : ditto
+
+ * oniguruma.h : ditto
+
+ * pack.c : ditto
+
+ * process.c : ditto
+
+ * random.c : ditto
+
+ * range.c : ditto
+
+ * rb/ir.rb : ditto
+
+ * re.c : ditto
+
+ * regcomp.c : ditto
+
+ * regenc.c : ditto
+
+ * regenc.h : ditto
+
+ * regerror.c : ditto
+
+ * regexec.c : ditto
+
+ * regint.h : ditto
+
+ * regparse.c : ditto
+
+ * regparse.h : ditto
+
+ * ruby.c : ditto
+
+ * ruby.h : ditto
+
+ * rubyio.h : ditto
+
+ * sjis.c : ditto
+
+ * sprintf.c : ditto
+
+ * st.c : ditto
+
+ * st.h : ditto
+
+ * struct.c : ditto
+
+ * test/ruby/envutil.rb : ditto
+
+ * test/ruby/test_struct.rb : ditto
+
+ * time.c : ditto
+
+ * utf8.c : ditto
+
+ * util.c : ditto
+
+ * util.h : ditto
+
+ * version.h : ditto
+
+ * win32/Makefile.sub : ditto
+
+ * win32/win32.c : ditto
+
+
+2006-02-14(Tue) 16:40:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, eval_proc.c : fix rb_proc_arity
+
+ * eval.c : declare funcall same as send (temporarily)
+
+ * lib/thread.rb : added
+
+ * test/pathname/test_pathname.rb : imported from ruby 1.9
+
+ * test/scanf/data.txt : ditto
+
+ * test/scanf/test_scanf.rb : ditto
+
+ * test/scanf/test_scanfblocks.rb : ditto
+
+ * test/scanf/test_scanfio.rb : ditto
+
+ * test/socket/test_socket.rb : ditto
+
+ * test/socket/test_tcp.rb : ditto
+
+ * test/socket/test_udp.rb : ditto
+
+ * test/socket/test_unix.rb : ditto
+
+ * test/stringio/test_stringio.rb : ditto
+
+ * test/uri/test_common.rb : ditto
+
+ * test/uri/test_ftp.rb : ditto
+
+ * test/uri/test_generic.rb : ditto
+
+ * test/uri/test_http.rb : ditto
+
+ * test/uri/test_ldap.rb : ditto
+
+ * test/uri/test_mailto.rb : ditto
+
+
+2006-02-14(Tue) 15:59:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c : Change Thread.critical warnning message
+
+ * lib/webrick.rb : imported from ruby 1.9
+
+ * lib/webrick/accesslog.rb : ditto
+
+ * lib/webrick/cgi.rb : ditto
+
+ * lib/webrick/compat.rb : ditto
+
+ * lib/webrick/config.rb : ditto
+
+ * lib/webrick/cookie.rb : ditto
+
+ * lib/webrick/htmlutils.rb : ditto
+
+ * lib/webrick/httpauth.rb : ditto
+
+ * lib/webrick/httpauth/authenticator.rb : ditto
+
+ * lib/webrick/httpauth/basicauth.rb : ditto
+
+ * lib/webrick/httpauth/digestauth.rb : ditto
+
+ * lib/webrick/httpauth/htdigest.rb : ditto
+
+ * lib/webrick/httpauth/htgroup.rb : ditto
+
+ * lib/webrick/httpauth/htpasswd.rb : ditto
+
+ * lib/webrick/httpauth/userdb.rb : ditto
+
+ * lib/webrick/httpproxy.rb : ditto
+
+ * lib/webrick/httprequest.rb : ditto
+
+ * lib/webrick/httpresponse.rb : ditto
+
+ * lib/webrick/https.rb : ditto
+
+ * lib/webrick/httpserver.rb : ditto
+
+ * lib/webrick/httpservlet.rb : ditto
+
+ * lib/webrick/httpservlet/abstract.rb : ditto
+
+ * lib/webrick/httpservlet/cgi_runner.rb : ditto
+
+ * lib/webrick/httpservlet/cgihandler.rb : ditto
+
+ * lib/webrick/httpservlet/erbhandler.rb : ditto
+
+ * lib/webrick/httpservlet/filehandler.rb : ditto
+
+ * lib/webrick/httpservlet/prochandler.rb : ditto
+
+ * lib/webrick/httpstatus.rb : ditto
+
+ * lib/webrick/httputils.rb : ditto
+
+ * lib/webrick/httpversion.rb : ditto
+
+ * lib/webrick/log.rb : ditto
+
+ * lib/webrick/server.rb : ditto
+
+ * lib/webrick/ssl.rb : ditto
+
+ * lib/webrick/utils.rb : ditto
+
+ * lib/webrick/version.rb : ditto
+
+
+2006-02-14(Tue) 14:55:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : support "defined?($1)", ...
+
+ * yarvtest/test_syntax.rb : add a test for above
+
+ * rb/makedocs.rb : fix template directory path
+
+ * vm.c : fix to handle break from proc
+
+
+2006-02-14(Tue) 12:42:59 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : fix rb_iterate hook
+
+ * yarvtest/test_block.rb : add a tests for above
+
+ * vm.c : remove unused comment
+
+
+2006-02-14(Tue) 12:01:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : fix to check passed block at block_given_p
+
+ * eval_proc.c : fix to pass block at Method#call
+
+ * runruby.rb : fix to apply ruby
+
+ * test/runner.rb : GC.stress (comment out)
+
+ * vm.c : fix indnet
+
+
+2006-02-14(Tue) 08:04:33 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/tempfile.rb: use Mutex instead of Thread.critical.
+
+ * lib/rss/dublincore.rb: |x,| -> |x,_| to avoid YARV bug (tmp).
+
+ * lib/rexml: imported from ruby CVS trunk HEAD.
+
+ * test/digest: ditto.
+
+ * test/fileutils: ditto.
+
+ * test/ostruct: ditto.
+
+ * test/erb: ditto.
+
+ * test/optparse: ditto.
+
+ * test/ruby/test_signal.rb: turn off a test to avoid unknown error
+ (tmp).
+
+
+2006-02-14(Tue) 07:52:03 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/digest: imported from ruby CVS trunk HEAD.
+
+ * test/fileutils: ditto.
+
+ * test/ostruct: ditto.
+
+ * test/erb: ditto.
+
+ * test/optparse: ditto.
+
+
+2006-02-14(Tue) 06:26:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, parse.y : support BEGIN{} (remove local scope)
+
+ * test/ruby/beginmainend.rb : fix to apply YARV's specification
+
+ * test/ruby/test_beginendblock.rb : enable BEGIN{} test
+
+ * signal.c : exit at double segv
+
+ * insns.def (preexe) : remove instruction "preexe"
+
+
+2006-02-14(Tue) 05:53:56 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * eval.c (ruby_cleanup): th->errinfo contains a NODE while
+ break'ing, check it before refering klass.
+
+
+2006-02-14(Tue) 05:45:07 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix stack calc of send
+
+ * sample/test.rb : remove SEGV causing code
+
+
+2006-02-14(Tue) 02:24:21 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_module.rb: list order is not a matter.
+
+ * test/csv: imported from ruby CVS trunk HEAD.
+
+
+2006-02-14(Tue) 02:06:25 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_beginendblock.rb: unlock tests.
+
+ * test/ruby/beginmainend.rb: new file (imported from ruby CVS
+ trunk HEAD).
+
+ * test/ruby/endblockwarn.rb: new file (imported from ruby CVS
+ trunk HEAD).
+
+ * test/ruby/test_file.rb: new file (imported from ruby CVS trunk
+ HEAD).
+
+
+2006-02-14(Tue) 01:42:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * error.c : fix include file positon
+
+ * test/ruby/test_signal.rb : skip test_exit_action on cygwin
+
+
+2006-02-14(Tue) 01:36:57 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_class.rb: new file (imported from rubicon).
+
+
+2006-02-14(Tue) 01:32:23 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_module.rb: ignore PP mixins.
+
+
+2006-02-14(Tue) 01:24:56 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_lambda.rb: removed (->(){...} syntax is
+ obsolete).
+
+
+2006-02-14(Tue) 01:20:54 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_module.rb: import many tests from rubicon.
+
+
+2006-02-14(Tue) 01:06:57 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix to avoid stack consistency error
+
+ * yarvtest/test_exception.rb : add a test for above
+
+
+2006-02-14(Tue) 00:42:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, vm_macro.def : rename VM_CALL_SUPER to VM_CALL_SUPER_BIT
+
+ * insns.def (send) : set a flag of super as fcall
+
+ * yarvtest/test_class.rb : add a test for above
+
+
+2006-02-14(Tue) 00:31:24 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_eval.rb: fix typo.
+
+ * test/ruby/test_signal.rb: unlock tests.
+
+
+2006-02-13(Mon) 23:53:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, vm_macro.def : fix NODE_ZSUPER dispatch and
+ fix error message when super without suitable method ([yarv-dev:846])
+
+ * yarvcore.h : add VM_CALL_SUPER definition
+
+ * yarvtest/test_method.rb : add a test of Module#private_class_method
+
+
+2006-02-13(Mon) 22:49:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : traverse all iseq to find super method ([yarv-dev:859])
+
+ * yarvtest/test_class.rb : add a test for above
+
+ * yarvcore.c : add clear iseq->defined_method_id
+
+ * signal.c : fix to prohibit double segv handler kicked
+
+
+2006-02-13(Mon) 22:09:12 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_DECL, NODE_CLASS with NODE_CLON3 prefix
+
+ * yarvtest/test_class.rb : add tests for above
+
+
+2006-02-13(Mon) 21:20:57 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix indent
+
+ * compile.c : fix to prohibit "redo" from eval expression
+
+
+2006-02-13(Mon) 20:36:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : fix constant search bug ([yarv-dev:788])
+
+ * yarvtest/test_class.rb : add a test of [yarv-dev:788]
+
+
+2006-02-13(Mon) 18:09:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/ruby/test_clone.rb : enable tests with Class#clone
+
+ * test/ruby/test_marshal.rb : ditto
+
+
+2006-02-13(Mon) 17:42:37 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * class.c : support Class#clone
+
+ * compile.c, insns.def : remove popcref
+
+ * yarvcore.h, vm.c, insns.def : remove yarv_thread_t#cref_stack
+
+ * eval.c, eval_intern.h, eval_load.c : ditto
+
+ * yarvtest/test_class.rb : add tests for singleton class
+
+ * gc.c : remove "FRAME *" unused variable
+
+ * insnhelper.h : fix COPY_CREF
+
+ * rb/mklog.rb : add default message
+
+ * vm_macro.def : support NODE_ZSUPER as method type
+
+
+2006-02-13(Mon) 00:11:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * blockinlining.c : refoctoring with CFLAGS+=-Wunused
+
+ * eval.c : ditto
+
+ * eval_intern.h : ditto
+
+ * eval_load.c : ditto
+
+ * eval_method.h : ditto
+
+ * eval_proc.c : ditto
+
+ * eval_thread.c : ditto
+
+ * insns.def : ditto
+
+ * parse.y : ditto
+
+ * thread.c : ditto
+
+ * vm.c : ditto
+
+
+2006-02-13(Mon) 02:32:34 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_const.rb: show better message.
+
+ * test/ruby/test_eval.rb: ditto.
+
+ * test/ruby/test_module.rb: new file.
+
+
+2006-02-12(Sun) 22:22:35 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * array.c : revert last commit
+
+ * ascii.c : ditto
+
+ * bignum.c : ditto
+
+ * class.c : ditto
+
+ * compar.c : ditto
+
+ * defines.h : ditto
+
+ * dir.c : ditto
+
+ * dln.c : ditto
+
+ * dln.h : ditto
+
+ * enum.c : ditto
+
+ * enumerator.c : ditto
+
+ * error.c : ditto
+
+ * euc_jp.c : ditto
+
+ * file.c : ditto
+
+ * gc.c : ditto
+
+ * hash.c : ditto
+
+ * intern.h : ditto
+
+ * io.c : ditto
+
+ * lex.c : ditto
+
+ * main.c : ditto
+
+ * marshal.c : ditto
+
+ * math.c : ditto
+
+ * missing.h : ditto
+
+ * node.h : ditto
+
+ * numeric.c : ditto
+
+ * object.c : ditto
+
+ * oniguruma.h : ditto
+
+ * pack.c : ditto
+
+ * prec.c : ditto
+
+ * process.c : ditto
+
+ * random.c : ditto
+
+ * range.c : ditto
+
+ * rb/mklog.rb : ditto
+
+ * re.c : ditto
+
+ * regcomp.c : ditto
+
+ * regenc.c : ditto
+
+ * regenc.h : ditto
+
+ * regerror.c : ditto
+
+ * regex.h : ditto
+
+ * regexec.c : ditto
+
+ * regint.h : ditto
+
+ * regparse.c : ditto
+
+ * regparse.h : ditto
+
+ * ruby.c : ditto
+
+ * ruby.h : ditto
+
+ * rubyio.h : ditto
+
+ * rubysig.h : ditto
+
+ * signal.c : ditto
+
+ * sjis.c : ditto
+
+ * sprintf.c : ditto
+
+ * st.c : ditto
+
+ * st.h : ditto
+
+ * string.c : ditto
+
+ * struct.c : ditto
+
+ * time.c : ditto
+
+ * utf8.c : ditto
+
+ * util.c : ditto
+
+ * util.h : ditto
+
+ * variable.c : ditto
+
+ * version.c : ditto
+
+
+2006-02-12(Sun) 21:33:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * array.c : fix to ruby's indent
+
+ * ascii.c : ditto
+
+ * bignum.c : ditto
+
+ * blockinlining.c : ditto
+
+ * call_cfunc.h : ditto
+
+ * class.c : ditto
+
+ * compar.c : ditto
+
+ * compile.c : ditto
+
+ * compile.h : ditto
+
+ * debug.c : ditto
+
+ * debug.h : ditto
+
+ * defines.h : ditto
+
+ * dir.c : ditto
+
+ * disasm.c : ditto
+
+ * dln.c : ditto
+
+ * dln.h : ditto
+
+ * enum.c : ditto
+
+ * enumerator.c : ditto
+
+ * error.c : ditto
+
+ * euc_jp.c : ditto
+
+ * eval.c : ditto
+
+ * eval_error.h : ditto
+
+ * eval_intern.h : ditto
+
+ * eval_jump.h : ditto
+
+ * eval_load.c : ditto
+
+ * eval_method.h : ditto
+
+ * eval_proc.c : ditto
+
+ * eval_safe.h : ditto
+
+ * eval_thread.c : ditto
+
+ * file.c : ditto
+
+ * gc.c : ditto
+
+ * hash.c : ditto
+
+ * insnhelper.h : ditto
+
+ * insns.def : ditto
+
+ * intern.h : ditto
+
+ * io.c : ditto
+
+ * lex.c : ditto
+
+ * main.c : ditto
+
+ * marshal.c : ditto
+
+ * math.c : ditto
+
+ * missing.h : ditto
+
+ * node.h : ditto
+
+ * numeric.c : ditto
+
+ * object.c : ditto
+
+ * oniguruma.h : ditto
+
+ * opt_insn_unif.def : ditto
+
+ * opt_operand.def : ditto
+
+ * pack.c : ditto
+
+ * prec.c : ditto
+
+ * process.c : ditto
+
+ * random.c : ditto
+
+ * range.c : ditto
+
+ * re.c : ditto
+
+ * re.h : ditto
+
+ * regcomp.c : ditto
+
+ * regenc.c : ditto
+
+ * regenc.h : ditto
+
+ * regerror.c : ditto
+
+ * regex.h : ditto
+
+ * regexec.c : ditto
+
+ * regint.h : ditto
+
+ * regparse.c : ditto
+
+ * regparse.h : ditto
+
+ * ruby.c : ditto
+
+ * ruby.h : ditto
+
+ * rubyio.h : ditto
+
+ * rubysig.h : ditto
+
+ * signal.c : ditto
+
+ * sjis.c : ditto
+
+ * sprintf.c : ditto
+
+ * st.c : ditto
+
+ * st.h : ditto
+
+ * string.c : ditto
+
+ * struct.c : ditto
+
+ * test.rb : ditto
+
+ * thread.c : ditto
+
+ * thread_pthread.h : ditto
+
+ * thread_win32.h : ditto
+
+ * time.c : ditto
+
+ * utf8.c : ditto
+
+ * util.c : ditto
+
+ * util.h : ditto
+
+ * variable.c : ditto
+
+ * version.c : ditto
+
+ * vm.c : ditto
+
+ * vm.h : ditto
+
+ * vm_dump.c : ditto
+
+ * vm_evalbody.h : ditto
+
+ * vm_macro.def : ditto
+
+ * yarv.h : ditto
+
+ * yarv_version.h : ditto
+
+ * yarvcore.c : ditto
+
+ * yarvcore.h : ditto
+
+
+2006-02-12(Sun) 15:53:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/abbrev.rb : added
+
+ * lib/base64.rb : ditto
+
+ * lib/cgi-lib.rb : ditto
+
+ * lib/csv.rb : ditto
+
+ * lib/date2.rb : ditto
+
+ * lib/eregex.rb : ditto
+
+ * lib/ipaddr.rb : ditto
+
+ * lib/irb.rb : ditto
+
+ * lib/irb/cmd/chws.rb : ditto
+
+ * lib/irb/cmd/fork.rb : ditto
+
+ * lib/irb/cmd/help.rb : ditto
+
+ * lib/irb/cmd/load.rb : ditto
+
+ * lib/irb/cmd/nop.rb : ditto
+
+ * lib/irb/cmd/pushws.rb : ditto
+
+ * lib/irb/cmd/subirb.rb : ditto
+
+ * lib/irb/completion.rb : ditto
+
+ * lib/irb/context.rb : ditto
+
+ * lib/irb/ext/change-ws.rb : ditto
+
+ * lib/irb/ext/history.rb : ditto
+
+ * lib/irb/ext/loader.rb : ditto
+
+ * lib/irb/ext/math-mode.rb : ditto
+
+ * lib/irb/ext/multi-irb.rb : ditto
+
+ * lib/irb/ext/save-history.rb : ditto
+
+ * lib/irb/ext/tracer.rb : ditto
+
+ * lib/irb/ext/use-loader.rb : ditto
+
+ * lib/irb/ext/workspaces.rb : ditto
+
+ * lib/irb/extend-command.rb : ditto
+
+ * lib/irb/frame.rb : ditto
+
+ * lib/irb/help.rb : ditto
+
+ * lib/irb/init.rb : ditto
+
+ * lib/irb/input-method.rb : ditto
+
+ * lib/irb/lc/error.rb : ditto
+
+ * lib/irb/lc/help-message : ditto
+
+ * lib/irb/lc/ja/CVS/Entries : ditto
+
+ * lib/irb/lc/ja/CVS/Repository : ditto
+
+ * lib/irb/lc/ja/CVS/Root : ditto
+
+ * lib/irb/lc/ja/error.rb : ditto
+
+ * lib/irb/lc/ja/help-message : ditto
+
+ * lib/irb/locale.rb : ditto
+
+ * lib/irb/notifier.rb : ditto
+
+ * lib/irb/output-method.rb : ditto
+
+ * lib/irb/ruby-lex.rb : ditto
+
+ * lib/irb/ruby-token.rb : ditto
+
+ * lib/irb/slex.rb : ditto
+
+ * lib/irb/version.rb : ditto
+
+ * lib/irb/workspace.rb : ditto
+
+ * lib/irb/ws-for-case-2.rb : ditto
+
+ * lib/irb/xmp.rb : ditto
+
+ * lib/jcode.rb : ditto
+
+ * lib/logger.rb : ditto
+
+ * lib/mailread.rb : ditto
+
+ * lib/mathn.rb : ditto
+
+ * lib/parsedate.rb : ditto
+
+ * lib/pathname.rb : ditto
+
+ * lib/ping.rb : ditto
+
+ * lib/pstore.rb : ditto
+
+ * lib/resolv-replace.rb : ditto
+
+ * lib/resolv.rb : ditto
+
+ * lib/rss.rb : ditto
+
+ * lib/rss/0.9.rb : ditto
+
+ * lib/rss/1.0.rb : ditto
+
+ * lib/rss/2.0.rb : ditto
+
+ * lib/rss/content.rb : ditto
+
+ * lib/rss/converter.rb : ditto
+
+ * lib/rss/dublincore.rb : ditto
+
+ * lib/rss/image.rb : ditto
+
+ * lib/rss/maker.rb : ditto
+
+ * lib/rss/maker/0.9.rb : ditto
+
+ * lib/rss/maker/1.0.rb : ditto
+
+ * lib/rss/maker/2.0.rb : ditto
+
+ * lib/rss/maker/base.rb : ditto
+
+ * lib/rss/maker/content.rb : ditto
+
+ * lib/rss/maker/dublincore.rb : ditto
+
+ * lib/rss/maker/image.rb : ditto
+
+ * lib/rss/maker/syndication.rb : ditto
+
+ * lib/rss/maker/taxonomy.rb : ditto
+
+ * lib/rss/maker/trackback.rb : ditto
+
+ * lib/rss/parser.rb : ditto
+
+ * lib/rss/rexmlparser.rb : ditto
+
+ * lib/rss/rss.rb : ditto
+
+ * lib/rss/syndication.rb : ditto
+
+ * lib/rss/taxonomy.rb : ditto
+
+ * lib/rss/trackback.rb : ditto
+
+ * lib/rss/utils.rb : ditto
+
+ * lib/rss/xml-stylesheet.rb : ditto
+
+ * lib/rss/xmlparser.rb : ditto
+
+ * lib/rss/xmlscanner.rb : ditto
+
+ * lib/rubyunit.rb : ditto
+
+ * lib/scanf.rb : ditto
+
+ * lib/shell.rb : ditto
+
+ * lib/singleton.rb : ditto
+
+ * lib/tsort.rb : ditto
+
+ * lib/weakref.rb : ditto
+
+ * eval_jump.c : removed
+
+
+2006-02-12(Sun) 15:39:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * parse.y : fix to remove including env.h
+
+ * yarvtest/test_exception.rb : fix syntax (add 'end')
+
+
+2006-02-12(Sun) 15:14:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * env.h : removed
+
+ * common.mk : remove env.h dependency
+
+ * compile.c, eval_intern.h : remove include env.h
+
+ * vm.c : ditto
+
+ * ruby.h, gc.c, error.c : remove T_SCOPE, T_VARMAP
+
+ * parse.y, eval.c : use rb_parse_in_eval() instead of ruby_in_eval
+
+ * yarvcore.c, yarvcore.h : add a prase_in_eval member to yarv_thread_t
+
+ * insns.def : add push value to throw instruction
+ for stack consistency
+
+ * yarvtest/test_exception.rb : add a test for above
+
+ * test/ruby/test_gc.rb : fix typo
+
+
+2006-02-12(Sun) 05:05:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c, eval_intern.h, eval_load.c, eval_proc.c, node.h,
+ insnhelper.h, insns.def, vm.c, yarvcore.c, yarvcore.h :
+ change cref data structure and unify ruby_class and ruby_cbase
+ and some refoctoring
+
+
+2006-02-11(Sat) 23:41:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def (methoddef) : fix method declaration in method
+
+ * thread.c : Thread.critical to show warning (no effect)
+
+
+2006-02-11(Sat) 20:20:18 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix [yarv-dev:831]
+
+ * yarvtest/test_class.rb : add a test for above
+
+
+2006-02-11(Sat) 14:29:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/mklog.rb : use svk
+
+ * error.c : remove newline
+
+ * eval.c (rb_block_call) : added
+
+ * eval_thread.c : remove some unused functions, comments
+
+ * thread.c : add comments (move from eval_thread.c) and support Mutex
+
+ * thread.c (rb_thread_select) : supported
+
+ * thread_pthread.h (native_mutex_trylock) : added (macro)
+
+ * thread_win32.h (native_mutex_trylock) : added
+
+ * yarvcore.c : remove unused code
+
+ * array.c : import ruby 1.9
+
+ * compar.c : ditto
+
+ * dln.c : ditto
+
+ * enum.c : ditto
+
+ * enumerator.c : ditto
+
+ * ext/digest/digest.c : ditto
+
+ * ext/digest/digest.h : ditto
+
+ * ext/digest/sha2/sha2.c : ditto
+
+ * ext/etc/etc.c : ditto
+
+ * ext/win32ole/win32ole.c : ditto
+
+ * hash.c : ditto
+
+ * intern.h : ditto
+
+ * io.c : ditto
+
+ * main.c : ditto
+
+ * missing.h : ditto
+
+ * missing/flock.c : ditto
+
+ * missing/isinf.c : ditto
+
+ * missing/vsnprintf.c : ditto
+
+ * lib/cgi.rb : ditto
+
+ * lib/complex.rb : ditto
+
+ * lib/delegate.rb : ditto
+
+ * lib/erb.rb : ditto
+
+ * lib/fileutils.rb : ditto
+
+ * lib/matrix.rb : ditto
+
+ * lib/mkmf.rb : ditto
+
+ * lib/optparse.rb : ditto
+
+ * lib/ostruct.rb : ditto
+
+ * lib/pp.rb : ditto
+
+ * lib/timeout.rb : ditto
+
+ * lib/tmpdir.rb : ditto
+
+ * lib/test/unit/autorunner.rb : ditto
+
+ * node.h : ditto
+
+ * object.c : ditto
+
+ * parse.y : ditto
+
+ * ruby.c : ditto
+
+ * sample/test.rb : ditto
+
+ * sprintf.c : ditto
+
+ * st.c : ditto
+
+ * test/ruby/test_whileuntil.rb : ditto
+
+ * test/runner.rb : ditto
+
+ * time.c : ditto
+
+ * lib/net/.document : added
+
+ * lib/net/ftp.rb : ditto
+
+ * lib/net/http.rb : ditto
+
+ * lib/net/https.rb : ditto
+
+ * lib/net/imap.rb : ditto
+
+ * lib/net/pop.rb : ditto
+
+ * lib/net/protocol.rb : ditto
+
+ * lib/net/smtp.rb : ditto
+
+ * lib/net/telnet.rb : ditto
+
+ * lib/open-uri.rb : ditto
+
+
+2006-02-10(Fri) 08:07:34 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def, yarvcore.h : support defined?(private_method) and
+ defined?(protected_method) (separate DEFINE_METHOD / DEFINE_FUNC)
+
+ * yarvtest/test_syntax.rb : add a test for above
+
+ * compile.c (iseq_compile_each) : fix NODE_RETURN bug
+ (double ensure invoke)
+
+ * yarvtest/test_flow.rb : add a test for above
+
+ * eval.c (get_errinfo) : fix to search $!
+
+ * yarvtest/test_exception.rb : add tests for above
+
+ * eval_safe.h : support $SAFE
+
+ * ext/socket/socket.c : import ruby 1.9
+
+ * gc.c (gc_mark_children) : fix making T_VALUE
+
+ * test/ruby/test_gc.rb : use GC.stress
+
+ * signal.c (sighandler) : send interrupt signal if thread blocked
+
+ * test/ruby/test_proc.rb : remove assert false
+
+ * test/ruby/test_readpartial.rb : change fail message
+
+ * test/ruby/test_signal.rb : remove assert false
+
+ * thread.c (thread_start_func_2) : set local_lfp/local_svar
+ at thread creation
+
+ * thread_pthread.h : export native_thread_interrupt
+
+ * thread_win32.h : export native_thread_interrupt
+
+ * version.h : import ruby 1.9
+
+ * vm.c (lfp_svar), yarvcore.h : fix to use Thread local svar
+
+ * yarvtest/test_thread.rb : add a test for above
+
+ * win32/Makefile.sub : import ruby 1.9
+
+ * win32/dir.h : ditto
+
+ * win32/setup.mak : ditto
+
+ * win32/win32.c : ditto
+
+ * yarvtest/yarvtest.rb : fix to remove using ARGV
+
+
+2006-02-10(Fri) 01:04:58 +0900 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (rb_gc_call_finalizer_at_exit): turn on during_gc while
+ invoking finalizers.
+
+ * gc.c (rb_gc_finalize_deferred): ditto.
+
+
+2006-02-08(Wed) 23:17:44 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_proc.rb: method names were wrongly duplicated.
+
+
+2006-02-08(Wed) 21:30:01 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * ext/nkf: added (imported from ruby CVS trunk HEAD).
+
+ * ext/nkf/depend: new file (rev 1.5).
+
+ * ext/nkf/extconf.rb: new file (rev 1.2).
+
+ * ext/nkf/nkf.c: new file (rev 1.12).
+
+ * ext/nkf/test.rb: new file (rev 1.7).
+
+ * ext/nkf/nkf-utf8/nkf.c: new file (rev 1.17).
+
+ * ext/nkf/nkf-utf8/config.h: new file (rev 1.4).
+
+ * ext/nkf/nkf-utf8/utf8tbl.c: new file (rev 1.6).
+
+ * ext/nkf/lib/kconv.rb: new file (rev 1.13).
+
+ * test/nkf: added (imported from ruby CVS trunk HEAD).
+
+ * test/nkf/test_kconv.rb: new file (rev 1.1).
+
+ * test/nkf/test_nkf.rb: new file (rev 1.1).
+
+
+2006-02-08(Wed) 21:07:36 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/find.rb: new file (imported from ruby CVS trunk HEAD,
+ rev 1.15).
+
+
+2006-02-07(Tue) 17:58:18 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : support BEGIN{} and add preexe instruction
+
+ * insns.def : fix getspecial/setspecial instructions
+ to catch up svar change
+
+ * test/ruby/test_system.rb : remove stopper
+
+ * thread.c (rb_thread_fd_writable) : add a debug output
+
+ * thread.c (rb_thread_wait_fd) : add a debug output
+
+ * vm.c (lfp_svar) : refactoring and fix some problems
+
+ * vm_dump.c (yarv_bug) : add branch
+
+ * yarv.h : remove unused declarations
+
+ * yarvcore.c (vm_free) : VM object should not free by GC
+
+
+2006-02-07(Tue) 14:42:25 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c, eval_load.c : remove rb_thread_start_1()
+
+ * eval.c : fix some prototypes and indents
+
+ * eval_thread.c, thread.c : move some functions
+ from eval_thread.c to thread.c
+
+ * signal.c (sighandler) : add line braek in error message
+
+ * yarvcore.c, yarvcore.h, thread.c : support ThreadGroup
+
+ * ruby.h, gc.c, vm.c : make new basic type RValue and T_VALUE.
+ RValue includes three values in itself. RValue is used as
+ svar
+
+
+2006-02-06(Mon) 23:51:41 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_hash.rb: import many tests from rubicon.
+
+
+2006-02-04(Sat) 18:36:41 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_array.rb: import many tests from rubicon.
+
+
+2006-02-04(Sat) 17:47:44 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_signal.rb (test_exit_action): lib/timeout.rb is
+ not implemented yet.
+
+
+2006-02-04(Sat) 17:42:31 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_readpartial.rb: lib/timeout.rb is not implemented
+ yet.
+
+
+2006-02-04(Sat) 16:22:38 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_pipe.rb: remove useless require.
+
+ * test/ruby/test_signal.rb: turn off the test case which causes
+ segmentation fault (tmp).
+
+
+2006-02-04(Sat) 08:19:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add dependency to yarvcore.h on signal.o
+
+ * compile.c (iseq_compile_each) : fix [yarv-dev:795] problem
+ (prohibit "break", "next" jump from eval)
+
+ * eval.c : fix indent
+
+ * eval_thread.c, thread.c : remove some functions and move to thread.c
+
+ * insns.def, vm.c : fix [yarv-dev:799] and [yarv-dev:800]
+
+ * yarvtest/test_class.rb : add a test for above
+
+ * test/ruby/test_gc.rb : remove GC.debug_flag control
+
+ * test/ruby/test_readpartial.rb : disable
+
+ * test/ruby/test_signal.rb : disable
+
+ * thread.c : fix thread_debug() and many bugs
+
+ * thread.c (yarv_thread_s_new) : move living_threads setting
+
+ * thread.c (yarv_thread_join) : fix
+
+ * thread_pthread.h : add type native_thread_data_t (dummy)
+ and support interrupt blocking thread
+
+ * thread_pthread.h (native_thread_apply_priority) : added
+
+ * thread_win32.h : add type native_thread_data_t (dummy)
+ and support interrupt blocking thread
+
+ * yarvcore.h : use win32 thread system on cygwin and fix
+ some struct members
+
+ * yarvtest/test_thread.rb : added
+
+
+2006-02-03(Fri) 00:08:09 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_string.rb: import many tests from rubicon.
+
+
+2006-02-02(Thu) 23:20:13 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/envutil.rb: new file (imported from ruby trunk HEAD).
+
+ * test/ruby/marshaltestlib.rb: ditto.
+
+ * test/ruby/test_array.rb: ditto.
+
+ * test/ruby/test_beginendblock.rb: ditto.
+
+ * test/ruby/test_clone.rb: ditto.
+
+ * test/ruby/test_dir.rb: ditto.
+
+ * test/ruby/test_env.rb: ditto.
+
+ * test/ruby/test_file.rb: ditto.
+
+ * test/ruby/test_float.rb: ditto.
+
+ * test/ruby/test_fnmatch.rb: ditto.
+
+ * test/ruby/test_hash.rb: ditto.
+
+ * test/ruby/test_io.rb: ditto.
+
+ * test/ruby/test_marshal.rb: ditto.
+
+ * test/ruby/test_math.rb: ditto.
+
+ * test/ruby/test_pack.rb: ditto.
+
+ * test/ruby/test_path.rb: ditto.
+
+ * test/ruby/test_pipe.rb: ditto.
+
+ * test/ruby/test_rand.rb: ditto.
+
+ * test/ruby/test_range.rb: ditto.
+
+ * test/ruby/test_readpartial.rb: ditto.
+
+ * test/ruby/test_regexp.rb: ditto.
+
+ * test/ruby/test_settracefunc.rb: ditto.
+
+ * test/ruby/test_signal.rb: ditto.
+
+ * test/ruby/test_sprintf.rb: ditto.
+
+ * test/ruby/test_string.rb: ditto.
+
+ * test/ruby/test_stringchar.rb: ditto.
+
+ * test/ruby/test_struct.rb: ditto.
+
+ * test/ruby/test_symbol.rb: ditto.
+
+ * test/ruby/test_system.rb: ditto.
+
+ * test/ruby/test_time.rb: ditto.
+
+ * test/ruby/ut_eof.rb: ditto.
+
+
+2006-02-02(Thu) 22:53:44 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_proc.rb: test [yarv-dev:777].
+
+
+2006-02-01(Wed) 03:51:39 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * gc.c : add GC.debug_flag= method
+
+ * insns.def : support method definition in method
+
+ * yarvtest/test_method.rb : add tests for above
+
+
+2006-01-29(Sun) 11:40:26 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_proc.c (proc_alloc) : fix [yarv-dev:777]
+
+ * yarvtest/test_proc.rb : add a test for above
+
+ * insns.def : fix [yarv-dev:782] and add YARV_CHECK_INTS()
+
+ * yarvtest/test_class.rb : add a test for above
+
+ * thread_win32.h : fix [yarv-dev-en:23]
+
+ * vm.c (th_call0) : add YARV_CHECK_INTS()
+
+
+2006-01-09(Mon) 11:56:34 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * yarvcore.h: add prototype (remove warning).
+
+ * vm.c (th_invoke_proc): make save variables volatile.
+
+ * eval.c (eval): initialize local variables (remove warnings).
+
+ * eval_thread.c (rb_exec_recursive): ditto.
+
+ * yarvcore.c (thread_mark): ditto.
+
+ * vm.c (th_invoke_proc): ditto.
+
+ * eval.c: remove useless prototypes.
+
+
+2006-01-09(Mon) 10:25:12 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * eval_thread.c: rb_thread_join is required to build ruby on
+ Linux.
+
+ * compile.c: unify coding style.
+
+ * yarvcore.c: ditto.
+
+
+2006-01-06(Fri) 09:21:34 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * vm.c: coding style change only.
+
+
+2006-01-04(Wed) 14:12:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c (ruby_init), eval_intern.h : use POP_TAG_INIT() at bootstrap
+
+ * eval_thread.c : remove unused functions and comments
+
+ * intern.h : expose rb_make_exception()
+
+ * signal.c : support signal
+
+ * thread.c (yarv_thread_execute_interrupts) : added
+
+ * thread_pthread.h (thread_timer) : set interrupt_flag of
+ current runnning threads
+
+ * vm.c (th_invoke_proc) : jump with JUMP_TAG() if some exception
+ occurres
+
+ * yarv.h : add yarv_set_current_running_thread_raw() for bootstrap
+
+ * yarvcore.c : add yarv_segv() and segv() method for test
+
+ * yarvcore.c (Init_yarvcore) : set yarv_thread_t#running_thread
+
+ * yarvcore.h : fix yarv_thread_t members
+
+
+2006-01-03(Tue) 22:25:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * disasm.c (insn_operand_intern) : fix to add child iseq
+
+ * eval.c, gc.c : remove obsolete static variables (ruby_scope,
+ ruby_dyna_vars, ruby_frame)
+
+ * eval.c (rb_mod_s_constants) : use ruby_cref()
+
+ * eval.c (eval) : use th_restore_klass()
+
+ * eval_proc.c (rb_f_binding) : use th_store_klass()
+
+ * insns.def (concatarray) : fix insn ([expr, *nil] => [expr])
+
+ * vm.c (th_set_env), insnhelper.h : remove macro
+
+ * vm.c (eval_get_cvar_base) : use get_cref
+
+ * vm.c (th_make_proc) : use th_store_klass()
+
+ * vm_macro.def (macro_eval_invoke_func) : fix option args size
+
+ * vm_macro.def (macro_eval_invoke_func) : raise stack overflow error
+
+ * yarvcore.h : add yarv_stored_klass_t type
+
+ * yarvcore.c : fix mark functions around yarv_stored_klass_t
+
+
+2006-01-01(Sun) 05:14:26 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * lib/benchmark.rb: new file (imported from original ruby, rev
+ 1.10).
+
+
+2006-01-01(Sun) 03:51:10 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * yarvcore.c: add prototype.
+
+ * re.c: remove warning: long -> unsigned long.
+
+ * debug.c: adjust coding style.
+
+ * yarv.h: ditto.
+
+
+2006-01-01(Sun) 03:43:33 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * variable.c: add prototype.
+
+ * eval.c: ditto.
+
+ * eval_load.c: ditto.
+
+
+2006-01-01(Sun) 02:41:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add address analyse to vtune rule
+
+ * rb/vtlh.rb : added for above
+
+ * rb/insns2vm.rb, template/vm.inc.tmpl : insert #line directive
+ to reference above
+
+ * vm_macro.def (macro_eval_invoke_cfunc) : fix indent
+
+ * yarvtest/test_method.rb : fix indent, spacing
+ and add a test for alias
+
+
+2005-12-31(Sat) 12:42:05 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add Intel VTune rule (make vtune)
+
+ * eval.c, yarvcore.h : fix to remove yarv_thread_t#local_*
+
+ * parse.y (top_local_init_gen) : fix a problem ([yarv-dev:765])
+
+ * yarvtest/test_eval.rb : add a test for above
+
+ * vm.c (thread_eval) :remove unused function
+
+ * yarvcore.c (Init_yarvcore) : remove YARVCore::Thread::eval method
+
+ * yarvcore.c (thread_eval) : remove unused function
+
+
+2005-12-31(Sat) 06:05:00 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c (eval_search_super_klass) : pass block to method missing
+
+ * vm_macro.def (macro_eval_invoke_method) : ditto
+
+ * yarvtest/test_method.rb : add a test for above
+
+
+2005-12-31(Sat) 03:11:14 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c (eval), eval_proc.c (rb_f_binding) : save klass, etc to
+ binding and use it at eval
+
+ * eval_intern.h : ditto
+
+ * yarvtest/test_eval.rb : add tests for above
+
+ * yarvcore.c (th_get_special_cref) : added
+
+ * yarvcore.h : add a prototype of above
+
+ * vm.c (th_get_cref) : refactoring
+
+ * vm.c (eval_get_ev_const) : fix SEGV at A::B (A is not class/module)
+ ([yarv-dev:758])
+
+ * yarvtest/test_bin.rb : add a test for above
+
+ * rb/mklog.rb : use external diff command and show function name
+
+
+2005-12-30(Fri) 19:07:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, yarvcore.h, eval.c, eval_proc.c : support
+ Ruby's Binding
+
+ * yarvcore.c : support TOPLEVEL_BINDING
+
+ * yarvtest/test_eval.rb : add tests for above
+
+
+2005-12-30(Fri) 13:12:28 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_eval.rb: more tests for
+ module_eval/instance_eval.
+
+
+2005-12-30(Fri) 05:06:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add dependency (yarvcore.h) for gc.c
+
+ * eval.c, eval_intern.h, eval_load.c, eval_method.h,
+ insns.def, insnhelper.h, vm.c, yarvcore.c, yarvcore.h :
+ re-write class reference
+
+ * yarvtest/test_eval.rb : added
+
+ * yarvtest/test_proc.rb :
+
+
+2005-12-29(Thu) 12:27:12 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, yarvcore.h :
+ remvoe needless yarv_iseq_t#rewind_frame_size
+
+
+2005-12-29(Thu) 11:17:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add dependency to test-all rule
+
+ * eval.c (rb_sourceline), vm.c (th_get_sourceline) :
+ fix to skip process if iseq is ifunc
+
+ * test/ruby/test_lambda.rb : assert(fail, ...) instead of assert_fail
+
+ * test/ruby/test_proc.rb : ditto
+
+ * vm_dump.c : fix stack dump (iseq name)
+
+ * vm_macro.def : store proc (block proc) to cfp#proc for GC mark
+
+ * yarvcore.c : mark above on thread_mark
+
+ * eval.c (exec_under) : replace block#self ([yarv-dev:751])
+
+
+2005-12-29(Thu) 01:56:46 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : fix setting of Proc cref ([yarv-dev:741])
+
+ * yarvcore.c : fix indent
+
+
+2005-12-29(Thu) 00:17:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * disasm.c : show (block) local variable simple (not as symbol)
+
+ * gc.c : fix syntax error
+
+
+2005-12-28(Wed) 23:35:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * class.c (method_entry) : fixed for undefed method ([yarv-dev:743])
+
+ * compile.c : fix errinfo dvar id (#$!)
+ and fix NODE_ERRINFO compilation
+
+ * eval_proc.c, yarvcore.c : support YARVCore::VM::Proc.new
+
+ * insns.def : remove useless TODO comments
+
+ * insns.def : fix to use strict array conversion on
+ checkarrayinclude
+
+ * insns.def : fix defined?(yield) ([yarv-dev:744])
+
+ * yarvcore.h : change yarv_iseq_t layout
+
+
+2005-12-28(Wed) 16:49:55 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_eval.rb: add TODO comment.
+
+ * test/ruby/test_iterator.rb: rename YARVCore::VM::Proc -> Proc
+ (tmp).
+
+ * test/ruby/test_lambda.rb: use assert_fail.
+
+ * test/ruby/test_proc.rb: ditto.
+
+
+2005-12-28(Wed) 16:28:35 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_clone.rb: removed (tmp).
+
+ * test/ruby/test_eval.rb: define missing method Object#funcall
+ (tmp).
+
+ * test/ruby/test_lambda.rb: turn off tests for "->".
+
+ * test/ruby/test_proc.rb: turn off tests for |&b|.
+
+ * test/ruby/test_proc.rb: turn off tests for $SAFE setter.
+
+
+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)
+
+ * disasm.c : support showing ID of method/dynamic local variables
+
+ * rb/allload.rb : add verbose version (it's enable by $DEBUG)
+
+ * template/insns.inc.tmpl, template/insns_info.inc.tmpl,
+ template/minsns.inc.tmpl, template/opt_sc.inc.tmpl,
+ template/optinsn.inc.tmpl, template/optunifs.inc.tmpl,
+ template/vmtc.inc.tmpl : fix a comment
+
+ * variable.c (mod_av_set) : fix to clear inline cache ([yarv-dev:720])
+
+ * eval_method.h : fix to clear inline method cache
+
+ * vm.c, rb/insns2vm.rb, template/insns_info.inc.tmpl, compile.c,
+ insns.def, vm_evalbody.h, vm_macro.def :
+ fix operands types (ulong -> num_t, ...)
+
+ * vm_macro.def : fix to check SPECIAL_CONST_P() at splat array
+ ([yarv-dev:722])
+
+ * yarvcore.c : fix to throw syntax error
+
+ * yarvcore.h, eval.c, eval_error.h, eval_jump.h :
+ add yarv_vm_t#exit_code to fix problem at cleanup ([yarv-dev:723])
+
+ * insns.def : fix to invoke zsuper in method defined by define_method
+ ([yarv-dev:704])
+
+ * yarvtest/test_class.rb : add tests for above
+
+ * yarvtest/test_method.rb : fix comments
+
+
+2005-12-27(Tue) 01:52:07 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * array.c, intern.h, insns.def : expose rb_ary_replace and use it
+ in insns.def
+
+ * eval.c : fix to use SCOPE_* to NOEX_*
+
+ * eval_intern.h : remove SCOPE_*
+ and fix SCOPE_TEST() and SCOPE_SET(f)
+
+ * eval_load.c : save and store klass and visibility
+ at require and load
+
+ * eval_method.h : fix undefed method node ([yarv-dev-en:8])
+
+ * eval_proc.c : fix define_method ([yarv-dev:704])
+
+ * insnhelper.h, vm.h : remove GET_VM_STATE_VERSION(),
+ INC_VM_STATE_VERSION() and move these to vm.h
+
+ * insns.def : supportintg visibility
+
+ * node.h : remove NOEX_RECV
+
+ * variable.c, vm.c : add rb_vm_change_state() and use it in
+ remove_const
+
+ * vm.c, insns.def, yarvcore.h, yarvcore.c : add eval_push_cref(),
+ eval_pop_cref() and th_cref_init to manage current visibility
+
+ * yarv.h : add a prototype of rb_vm_change_state()
+
+ * yarvcore.h, insns.def : add defined_method_id and support
+ super in define_method scope
+
+ * yarvtest/test_class.rb : add tests for above
+
+
+2005-12-26(Mon) 20:44:38 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_basicinstructions.rb: new file.
+
+
+2005-12-26(Mon) 08:40:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c (eval_get_ev_const) : fix to skip nil
+
+
+2005-12-26(Mon) 08:27:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insnhelper.h : fix GET_CVAR_EV_KLASS [yarv-dev:703]
+
+
+2005-12-26(Mon) 07:51:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : add emptstack insn for all NODE_RETURN
+ and optimize it if it's not needed
+
+ * yarvtest/test_flow.rb : add a test for above
+
+
+2005-12-26(Mon) 07:08:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c, gc.c : add "gc_debug_flag" to debug gc
+
+ * insns.def : add emptstack
+
+ * compile.c, rb/insns2vm.rb, template/insns_info.inc.tmpl :
+ change interface of insn_stack_increase
+
+ * compile.c : fix return from ensure in method [yarv-dev:702]
+
+ * yarvtest/test_flow.rb : add tests for above
+
+
+2005-12-26(Mon) 02:15:02 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/ruby/test_alias.rb: do not use unimplemented defined?.
+
+
+2005-12-26(Mon) 02:00:11 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * test/runner.rb: new file.
+
+ * test/ruby/test_alias.rb: new file.
+
+ * test/ruby/test_clone.rb: new file.
+
+ * test/ruby/test_eval.rb: new file.
+
+ * test/ruby/test_iterator.rb: new file.
+
+ * test/ruby/test_lambda.rb: new file.
+
+ * test/ruby/test_proc.rb: new file.
+
+ * test/ruby/test_super.rb: new file.
+
+ * test/ruby/test_assignment.rb: new file.
+
+ * test/ruby/test_bignum.rb: new file.
+
+ * test/ruby/test_call.rb: new file.
+
+ * test/ruby/test_case.rb: new file.
+
+ * test/ruby/test_condition.rb: new file.
+
+ * test/ruby/test_const.rb: new file.
+
+ * test/ruby/test_defined.rb: new file.
+
+ * test/ruby/test_exception.rb: new file.
+
+ * test/ruby/test_gc.rb: new file.
+
+ * test/ruby/test_ifunless.rb: new file.
+
+ * test/ruby/test_method.rb: new file.
+
+ * test/ruby/test_trace.rb: new file.
+
+ * test/ruby/test_variable.rb: new file.
+
+ * test/ruby/test_whileuntil.rb: new file.
+
+
+2005-12-25(Sun) 07:40:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * blockinlining.c, compile.c : fix block inlining
+
+ * rb/insns2vm.rb : fix to support tracing stack depth
+ with operands unification
+
+ * vm_dump.c : fix to print Qundef on stack dump
+
+
+2005-12-25(Sun) 01:45:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, compile.c, rb/insns2vm.rb, template/insns_info.inc.tmpl :
+ trace stack depth at compile time
+ and use it as cont_sp for exception handling
+
+ * yarvtest/test_exception.rb : add tests for above
+
+ * yarvtest/test_flow.rb : ditto
+
+ * Merry Xmas :)
+
+
+2005-12-24(Sat) 19:34:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, compile.h : fix ADD_CATCH_ENTRY and add LABEL#sp
+
+ * eval_jump.h : fix catch to remove illegal error
+
+
+2005-12-24(Sat) 09:05:23 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_method.h : change data structure for RClass#m_tbl
+
+ * class.c, eval.c, eval_proc.c : fix for above changes
+
+ * node.h, gc.c : change NODE_FBODY, NODE_METHOD members
+ for above changes
+
+ * insns.def : support private/protected visibility
+
+ * vm_macro.def : ditto
+
+ * vm.c : ditto
+
+ * thread.c : fix typo
+
+ * thread_pthread.h : fix typo
+
+ * thread_win32.h : fix typo
+
+ * eval.c, yarvcore.h : add yarv_thread_t#method_missing_reason
+ to pass method_missing reason and use it to build error message
+
+ * compile.c : use ADD_CALL instead of ADD_SEND for
+ NODE_X(D)STR, NODE_CONST (func)
+
+
+2005-12-22(Thu) 02:45:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarv_version.h, Changes : 0.3.3
+
+
+2005-12-20(Tue) 04:04:45 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix self::Const access
+
+ * yarvtest/test_bin.rb : add a test for above
+
+
+2005-12-20(Tue) 01:52:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix to expand VALUES value
+
+ * yarvtest/test_massign.rb : add a test for above
+
+
+2005-12-20(Tue) 01:32:35 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, insnhelper.h : fix cvar in singleton method/class
+
+ * yarvtest/test_bin.rb : add tests for above
+
+
+2005-12-20(Tue) 01:03:34 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, yarvcore.h : support all defined?() syntax
+
+ * compile.c : fix NODE_COLON2
+
+ * yarvtest/test_bin.rb : add or fix tests for above
+
+ * win32/* : update all
+
+
+2005-12-17(Sat) 10:46:08 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * vm_macro.def: fix printf type mismatch for LP64 system (again).
+
+ * parse.y: introduce descriptive macro for special values of
+ lvtbl->dvars.
+
+
+2005-12-17(Sat) 09:39:27 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * vm_macro.def (macro_eval_invoke_method): fix printf type mismatch
+ for LP64 system.
+
+
+2005-12-14(Wed) 03:49:40 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : change rescue/ensure iseq name
+
+ * eval.c, intern.h : fix a prototype
+
+ * insns.def, yarvcore.h : add trace_function
+
+ * vm.c : fix deadly bug (illegal pointer cast)
+
+ * vm_dump.c : remove unused local variables
+
+ * vm_macro.def : add parameter size check
+
+ * yarvtest/test_bin.rb : comment out 2 assertions
+
+
+2005-12-13(Tue) 03:55:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_proc.c : fix indent
+
+ * insns.def : fix getspecial instruction to return nil
+ if no entry
+
+ * yarvtest/test_syntax.rb : add a test for above
+
+ * lib/un.rb : added
+
+ * template/*.tmpl : fix typo
+
+
+2005-12-13(Mon) 01:38:17 +0900 Minero Aoki <aamine@loveruby.net>
+
+ * yarv.h: add prototypes.
+
+ * intern.h: ditto.
+
+ * eval.c: ditto.
+
+ * debug.c: ditto.
+
+ * thread_pthread.h: fix printf type mismatch for LP64 system
+ (Linux/AMD64).
+
+ * variable.c: ditto.
+
+ * object.c: ditto.
+
+ * gc.c: ditto.
+
+ * process.c: ditto.
+
+ * error.c: ditto.
+
+ * vm.c: ditto.
+
+ * vm.h: ditto.
+
+ * vm_dump.c: ditto.
+
+ * disasm.c: ditto.
+
+ * marshal.c: ditto.
+
+ * eval_thread.c: ditto.
+
+
+2005-12-11(Sun) 22:00:34 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : call "inherited" method when a class is inherited
+
+ * yarvcore.h : fix yarv_iseq_t field layout
+
+ * common.mk : add dependence on yarvcore.h to eval*.o files
+
+ * compile.c : fix NODE_POSTEXE logic
+
+ * insnhelper.h : use GC_GUARDED_PTR_REF instead of magic number
+
+ * eval_proc.c : fix indent
+
+ * configure : re-autoconf
+
+
+2005-12-10(Sat) 03:57:20 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : fix blockinlining.o build rule
+
+ * insns.def : remove logic for zsuper
+
+ * template/optinsn.inc.tmpl :
+
+ * vm.c : remove thread_yield_light_prepare, thread_yield_light_invoke
+
+ * compile.c : support NODE_ZSUPER with optargs, restarg
+
+ * yarvtest/test_class.rb : add tests for above
+
+
+2005-12-09(Fri) 01:13:37 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * array.c, numeric.c, range.c : add prototype of
+ block inlining function
+
+ * blockinlining.c, vm_opts.h.base : add block inlining flag
+
+ * common.mk, debug.h, debug.c : add debug_breakpoint() for gdb
+
+ * compile.c : fix to use size_t on compile_data_alloc(),
+ fix illegal cast, fix to set arg_simple at compiling block,
+
+ * compile.c, vm.c : fix NODE_NEXT, NODE_BREAK logic
+
+ * yarvtest/test_flow.rb : add a test for above
+
+ * yarvcore.c, yarvcore.h, compile.c, eval.c : remove
+ yarv_iseq_t#root_iseq and add yarv_iseq_t#local_iseq and fix
+ to use this member field
+
+ * eval_method.h : fix indent
+
+ * gc.c : fix indent
+
+ * insns.def, compile.c : remove "zsuper" instruction (use "super"
+ instead). This is because NODE_ZSUPER represent with only "super"
+ instruction
+
+ * yarvcore.c : add proc_arity
+
+
+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,
+ numeric.c, range.c : collect block inlining logic to blockinlining.c
+
+
+2005-12-03(Sat) 20:24:07 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * blockinlining.c, common.mk : add blockinlining.c
+
+ * yarvcore.c, yarvcore.h, blockinlining.c, compile.c, compile.h,
+ gc.c, node.h, numeric.c, range.c :
+ support block inlining for Integer#times, Range#each
+
+ * compile.c : fix to set block redo/next point at last,
+ and fix NODE_OP_ASGN1
+
+ * compile.c, vm.c : add specialized instruction "opt_le"
+
+ * disasm.c : fix to show block, and to show catch type as string
+ and change node_name logic
+
+ * eval_thread.c : fix function type declaration
+
+ * insns.def : add instruction "putundef", "opt_checkenv"
+ to support block inlining and add stack check routine
+
+ * lib/cgi.rb : add global variable $CGI_DONTINPUT
+
+ * opt_operand.def : add some operand unification rules
+
+ * rb/insns2vm.rb : fix operand unification logic for BLOCKISEQ
+
+ * vm.c : fix exception handling routine (collect stack operations)
+
+ * vm_macro.def : fix macro_eval_invoke_bmethod
+
+ * yarvsubst.c : removed
+
+ * yarvtest/test_syn.rb : rename to yarvtest/test_syntax.rb
+
+ * yarvtest/yarvtest.rb : remove tempfile explicitly
+
+
+2005-11-30(Wed) 01:13:57 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add vm_opts.h rule
+
+ * vm.c, insns.def : fix proc creation under class and block
+ environment
+
+
+2005-11-29(Tue) 16:39:07 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c, eval_proc.c, vm.c, vm_macro.def :
+ support define_method and invoke NODE_BMETHOD method
+
+
+2005-11-29(Tue) 13:18:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : add iseq_add_mark_object, iseq_add_mark_object_compile_time
+ and use it to mark objects on iseq
+
+ * compile.h, compile.c : remove cast on NEW_CHILD_ISEQVAL, NEW_ISEQVAL
+ and interface
+
+ * compile.c, disasm.c, insns.def, vm_macro.def, rb/insns2vm.rb :
+ add BLOCKISEQ parameter type
+
+ * gc.c : fix garbage_collect to return true if only allocate memory
+
+ * vm.c : fix insertion order of proc/env
+
+ * vm_evalbody.h : add typedef yarv_iseq_t *BLOCKISEQ
+
+ * yarvcore.c, yarvcore.c : add idTimes
+
+ * yarvcore.c : fix proc_mark, env_mark around iseq mark
+
+
+2005-11-28(Mon) 09:02:57 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def, vm_evalbody.h : support super
+ with splat argument and block (and zsuper with block)
+
+ * yarvtest/test_class.rb : add tests for above
+
+ * compile.c, yarvcore.h, yarvcore.c, insns.def, time.c, string.c :
+ add opt_succ insn
+
+ * eval_method.h : fix indent
+
+ * eval_thread.c : apply cast to vanish a warning
+
+ * lib/tempfile.rb, lib/tmpdir.rb : added
+
+ * vm.c : eval_method_missing added
+
+ * vm_macro.def : refactoring
+
+
+2005-11-21(Mon) 21:21:33 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, compile.h, yarvcore.c : remove "iseqobj"
+ variables and rename to "iseq"
+
+
+2005-11-21(Mon) 07:31:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix block parameter error
+
+ * ext/* : added
+
+ * lib/optparse* : added
+
+ * benchmark/bm_so_sieve.rb : fix parameter
+
+
+
+2005-11-21(Mon) 03:47:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : optimize condition in literal
+
+ * thread_win32.h : fix win32 thread function prototype
+
+
+2005-11-20(Sun) 17:58:24 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix NODE_AND/OR bug
+
+ * eval.c : support rb_frame_this_func()
+
+
+2005-11-20(Sun) 12:32:31 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, yarvcore.c, yarvcore.h : support NODE_OPT_N
+
+ * compile.h : add macro ADD_CALL
+
+ * debug.c : add debug_v() and change to use only printf
+ on debug_id()
+
+ * sample/test.rb :
+
+ * vm.c : fix make_proc_from_block
+
+
+2005-11-19(Sat) 14:55:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * import ruby 1.9.0 (2005-11-18)
+
+
+2005-11-19(Sat) 06:08:37 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/test : added
+
+
+2005-11-19(Sat) 05:48:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : useless jump elimination (if/unless destination)
+
+ * eval.c : rb_iter_break support,
+ fix rb_iterate (clear errinfo if break)
+
+ * eval_proc.c : support rb_node_arity (YARV_METHOD_NODE)
+
+ * insns.def : change variable name
+
+ * vm.c : fix th_invoke_yield and add th_iter_break()
+
+ * vm_dump.c : fix yarv_bug()
+
+ * yarvcore.c : fix proc_mark to check IFUNC node and add
+ global ruby method SDR() for debug
+
+ * yarvtest/test_syn.rb : add a test for all condition combination
+
+
+2005-11-15(Tue) 05:52:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/forwardable.rb : added
+
+ * common.mk : remove "vm.o : CFLAGS += -fno-crossjumping" rule
+
+ * compile.c, yarvcore.h, insns.def : add FCALL/VCALL flag
+
+ * compile.c, insns.def : add onceinlinecache instruction
+
+ * eval.c : support $!, $@, raise (== raise $!)
+
+ * opt_operand.def : add some unification rule (send flags)
+
+ * vm.c : fix return process
+
+ * vm_macro.def : fix option prameters
+
+ * yarvtest/test_method.rb : add tests for above
+
+
+2005-11-15(Tue) 00:42:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : support rb_frame_pop() and rb_frame_callee(),
+ add rb_sourcefile(), rb_souceline(),
+
+
+ * compile.c : support postposition while/until,
+ fix block parameter index
+
+ * yarvtest/test_syn.rb : add tests for above
+
+ * yarvcore.c : fix env_mark
+
+ * vm.h, yarvcore.h : move vm.h#cmethod_info to
+ yarvcore.h#yarv_cmethod_info
+
+ * vm.c : add th_get_sourceline()
+
+ * eval_intern.h : fix PASS_PASSED_BLOCK()
+
+ * eval_load.c : fix re-enter require (temporalily)
+
+ * insns.def : permit re-open class when superclass is same
+
+
+2005-11-11(Fri) 01:20:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : add "allload" rule
+
+ * compile.c, yarvcore.h, insns.def, vm_macro.def, disasm.c :
+ change arg_rest, arg_block offset (1)
+
+ * insns.def : add postexe instruction
+
+ * insns.def, vm.c : support rest block parameter
+
+ * yarvtest/test_block.rb : add tests for above
+
+ * rb/allload.rb : get path from ARGV
+
+ * vm_opts.h.base : set default off
+
+
+2005-11-01(Tue) 08:28:19 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/other-lang/eval.rb : fix path
+
+ * lib/English.rb, lib/cgi.rb, lib/complex.rb, lib/delegate.rb :
+ added
+
+
+2005-11-01(Tue) 08:18:33 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : push and pop values after checkincludearray for
+ stack caching
+
+
+2005-10-31(Mon) 15:37:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bm_app_mandelbrot.rb : added
+
+ * benchmark/bm_app_factorial.rb : fixed parameter
+
+ * benchmark/bm_so_count_words.rb, benchmark/run_rite.rb : use
+ real file
+
+ * common.mk : add "ext" rule, add some dependencies and add option
+ to bench-each rule (renamed from bench-item)
+
+ * compile.c : fix get_root_iseq_object (check iseq type),
+ support splat case/when. support //o (regexp)
+
+ * eval.c : support *_eval, fix rb_obj_call_init to pass block
+
+ * eval_jump.h : support throw/catch
+
+ * eval_load.c : save klass_nest_stack when require
+
+ * eval_method.h : fix ruby_cbase()
+
+ * insnhelper.h : GET_EV_KLASS checks toplevel or not
+
+ * insns.def, yarvcore.c : fix singleton method definition and fix
+ super class's method
+
+ * lib/shellwords.rb : use String() instead of String.new()
+
+ * vm.c : check class iseq or not when making Proc and
+ add eval_search_super_klass function
+
+ * vm.h : CMETHOD_INFO_P to yarvcore.h
+
+ * vm_macro.def : splat if object type is T_ARRAY
+
+ * vm_opts.h, vm_opts.h.base : rename to vm_opts.h.base
+ insns2vm.rb will copy it to build directory
+
+ * yarvcore.c : add Proc#[]
+
+ * yarvcore.h : change INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE
+ to 512
+
+ * yarvtest/test_* : invalidate splat non array code (like: "*1")
+
+ * yarvtest/yarvtest.rb : use tempfile instead of popen
+
+
+2005-10-28(Fri) 09:11:53 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvtest/test_method.rb : fix test
+
+
+2005-10-28(Fri) 08:43:29 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run_rite.rb : add -I options to run benchmark
+
+ * common.mk : pass options to some rules with RUNOPT
+ and add -I options
+
+ * compile.c : fix massign with constant
+
+ * yarvtest/test_massign.rb : add tests for above
+
+ * eval_load.c : fix load_wait()
+
+ * eval_method.h : support ruby_cbase()
+
+ * lib/*.rb : add or modify libraries to run on yarv
+ * parse.y : change to ANSI C style
+
+ * vm.c : fix making proc process under cfunc/ifunc environment
+
+ * vm_macro.def : fix block pass
+
+ * yarvtest/test_method.rb : add tests for above
+
+ * yarvcore.c : add yarv_obj_is_proc()
+
+ * eval.c : fix rb_obj_is_proc to use yarv_obj_is_proc()
+
+
+2005-10-27(Thu) 11:50:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * some files : import from ruby 1.9.0 (2005-10-12)
+
+
+2005-10-16(Sun) 14:50:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, compile.c, yarvcore.h, yarvcore.c : add insns "bitblt" and "answer"
+
+
+2005-10-11(Tue) 17:01:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarv_version.h, Changes : 0.3.2
+
+
+2005-10-11(Tue) 13:35:25 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : add YARV_CHECK_INTS()
+
+ * thread.c, thread_pthread.h, thread_win32.h : kick timer thread
+ when another thread kicked
+
+ * vm.c : remove debug print
+
+ * vm_opts.h : add OPT_CALL_THREADED_CODE
+
+ * yarvtest/yarvtest.rb : remove "\r" from answer
+
+
+2005-10-07(Fri) 09:36:36 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h : add member variable "interrupt_flag" to yarv_thread_t
+
+
+2005-10-05(Wed) 21:20:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eva.c, eval_thread.c, ruby.h, eval_error.h, eval_jump.h,
+ eval_load.c, thread.c, error.c, compile.h : remove ruby_errinfo
+
+ * thread_win32.h, thread_pthread.h : set stack size to 4KB
+
+ * vm.c : fix making env routine
+
+ * vm_dump.c, vm.h : support frame type "EVAL" and fix magic number
+
+ * yarvcore.c : fix some mark/free routine
+
+
+2005-10-05(Wed) 09:08:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c, eval_intern.h, vm.c, eval_jump.h, yarvcore.h :
+ re-define PUSH/POP/EXEC/JUMP_TAG to use thread local tag
+
+ * inits.c, yarvcore.c : fix boostrap
+
+
+2005-10-03(Mon) 22:28:24 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix NODE_COLON2 bugs
+
+ * compile.h : fix debug routine
+
+ * disasm.c : add space between insn and operand
+
+ * insns.def : add comment of classdef, singletonclassdef
+
+ * vm.c, yarv.h : fix invoke_light routine
+
+ * yarvcore.c : fix to mark each threads
+
+
+2005-10-02(Sun) 05:55:34 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread_pthread.h : add "system_working" global variable
+
+
+2005-10-02(Sun) 01:23:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c : add raw gets (for test), and fix indent
+
+
+2005-10-01(Sat) 23:06:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread_win32.h, common.mk : add thread_win32.h
+
+ * thread.c : support _WIN32 thread
+
+ * thread.c, thread_pthread.h : fix some interface
+
+ * eval_thread.c : remove debug print
+
+ * gc.c : fix stack region
+
+ * win32/Makefile.sub : add -MD flag to LDFLAGS
+
+ * yarvcore.c : fix mark and sweep debug print
+
+ * yarvcore.h : fix VM#living_threads data type to st_table
+
+
+2005-10-01(Sat) 00:25:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c, yarvcore.h : rename GIL (Global Interpreter Lock) to
+ GVL (Global VM Lock)
+
+ * thread_pthread.h : fix pthread mutex initialize
+
+
+2005-09-30(Fri) 20:11:19 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c : support join with timeout
+
+ * yarvcore.h : use GET_VM()
+
+
+2005-09-30(Fri) 14:59:29 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c, common.mk : add thread.c
+
+ * thread.c, gc.c, eval_thread.c, yarvcore.c, yarvcore.h :
+ support native thread (on pthread)
+
+ * insns.def : add YARV_CHECK_INTS() check
+
+ * yarv.h : add GET_VM() macro
+
+
+2005-09-29(Thu) 22:43:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_intern.h, eval_thread.c : move thread_status to eval_intern.h
+
+ * yarvcore.c : fix thread/vm value
+
+ * yarvcore.h : add some parameter to yarv_thread_t
+
+
+2005-09-29(Thu) 01:52:33 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, yarvcore.h : add line number on last end instruction
+
+ * vm.c : fix line no detection
+
+
+2005-09-28(Wed) 00:02:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk, eval_load.c, eval.c, eval_intern.h : add eval_load.c
+
+ * disasm.c : fix around block local variables
+
+ * eval_proc.c : fix typo
+
+
+2005-09-27(Tue) 16:45:20 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : remove debug print
+
+
+2005-09-27(Tue) 16:41:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : support Kernel.local_variables
+
+ * parse.y, yarvcore.c : move some functions
+ (rb_(backref|lastline)_(get|set)) from parse.y to yarvcore.c
+
+ * yarvcore.h : fix typo of YARV_PREVIOUS_CONTROL_FRAME
+
+
+2005-09-26(Mon) 18:51:29 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c, compile.c, parse.y, vm.c, yarvcore.h :
+ eval() works with binding (Env)
+
+ * vm.c : add th_set_eval_stack
+
+ * yarvtest/test_syn.rb : remove an assert "defined?(local_var)"
+
+
+2005-09-25(Sun) 19:30:59 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bm_vm2_send.rb : added
+
+ * common.mk : add rule "bench-item"
+
+ * eval_intern.h : add PASS_PASSED_BLOCK()
+
+ * eval_proc.c : support some functions
+
+ * rb/mklog.rb : added
+
+ * vm.c : fix prototype style and coding style
+
+ * yarv.h : add some prototypes of functions
+
+ * yarvcore.c, yarvcore.h, eval.c : yarv_thread_t#ifuncnode -> passed_block,
+ and add yarv_proc_t#safe_level
+
+
+2005-09-25(Sun) 11:01:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * some files : import from ruby 1.9.0 (2005-09-25)
+
+ * eval*, vm.c, vm_macro.def : remove frame, scope, ...
+
+ * yarvcore.c : remove yarv_block_given_p()
+
+ * yarvcore.h, insnhelper.h : move some macro from insnhelper.h to yarvcore.h
+ to use these in eval.c
+
+
+2005-09-24(Sat) 15:51:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval* : remove dependency to ruby_dyna_vars and ruby_class
+
+
+2005-09-23(Fri) 20:39:14 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval_*.[ch] : split eval.c to some files
+
+ * *.[ch] : import ruby 1.9.0 (2004-09-23)
+
+ * parse.y : remove dependency to ruby_dyna_vars and ruby_scope
+
+
+2005-09-15(Thu) 16:51:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, yarvcore.h : fix "for" scope
+
+ * yarvtest/test_block.rb : add tests for above
+
+
+2005-09-14(Wed) 06:11:43 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, vm_evalbody.h, vm.h, vm_dump.c,
+ compile.c, yarvcore.c : use #ifdef insted of #if for recognize
+ vm options
+
+ * vm_opts.h : fix default options
+
+
+2005-09-10(Sat) 14:10:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm_opts.h : added
+
+ * yarvcore.h, rb/insns2vm.h : use vm_opts.h
+
+
+2005-09-10(Sat) 04:53:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, insns.def, compile.c : add DEFINED_YIELD
+
+ * yarvtest/test_yield.rb : add test_1_ary_and_1_params
+
+ * insns.def : fix splat and svalue
+
+ * vm.c : fix to perform with proc with ifunc (incomplete)
+
+ * sample/test.rb : added (comment out unsupported features)
+
+ * common.mk : add rule "runtest"
+
+
+2005-09-09(Fri) 19:32:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, compile.c : add splatarray
+
+ * yarvtest/test_massign.rb : add tests for above
+
+
+2005-08-31(Wed) 22:55:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c (yarvcore_eval_parsed): fix to return value
+
+ * yarv_version.h, Changes : 0.3.1
+
+
+2005-08-20(Sat) 10:19:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/ir.rb : add some check
+
+ * import today's ruby HEAD
+
+
+2005-08-18(Thu) 23:29:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : fix object file extension
+
+ * rb/ir.rb : added (import ruby script)
+
+ * rb/diff.rb : removed
+
+ * import today's ruby HEAD
+
+
+2005-08-18(Thu) 12:59:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk : rule test -> test2, test1 -> test
+
+ * compile.c : fix when clause bug and splat arugment
+
+
+2005-08-17(Wed) 05:22:31 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix block local parameter setting routine and support
+ massign in block parameter initialze
+
+ * yarvtest/test_yield.rb : add tests for above
+
+ * insns.def, compile.c : support array concat (ex: "[x, *y]")
+
+ * yarvtest/test_bin.rb : add tests for above
+
+
+2005-08-16(Tue) 19:51:19 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support nested massign
+
+ * yarvtest/test_massign.rb : add tests for above
+
+
+2005-08-16(Tue) 10:25:29 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : support rb_yield_0 with 0 args
+
+
+2005-08-16(Tue) 09:09:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * lib/fileutils.rb : imported
+
+ * insns.def : fix yield argument (same as last commit)
+
+ * yarvtest/test_yield.rb : add tests for above
+
+
+2005-08-16(Tue) 08:29:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : fix to support rb_yield_0 with multiple values
+
+ * common.mk : add parse, run1p ruelse
+
+ * compile.c : support yield with ARGSCAT/SPLAT
+
+ * vm.c, insns.def : fix yield arguments to do compatible behaviour
+
+ * yarvtest/test_yield.rb : added for above
+
+
+2005-08-16(Tue) 06:00:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix to set klass_nest_stack on singleton
+ method definition
+
+ * yarvtest/test_method.rb : add a test for above
+
+
+2005-08-16(Tue) 05:34:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test1.rb : added. gdb and run1 rule run this script
+
+ * compile.c : fix error handled variable access
+
+ * yarvtest/test_exception.rb : add tests for above
+
+
+2005-08-16(Tue) 04:26:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * base ruby : ruby 1.9.0 (2005-08-15)
+
+
+2005-08-16(Tue) 03:54:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk, Makefile.in : move some rules to common.mk
+
+ * rb/diff.rb : added
+
+ * yarvtest/yarvtest.rb : fix to compare output last value
+
+
+2005-08-15(Mon) 18:27:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * Changes : 0.3.0
+
+
+2005-08-15(Mon) 17:56:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : fix to add prototype
+
+ * all files : propset svn:eol-style native
+
+
+2005-08-15(Mon) 10:48:53 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * eval.c : support rb_load
+
+
+2005-08-15(Mon) 09:42:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h : define SDR()
+
+ * vm_dump.c : stack_dump_raw() -> vm_stack_dump_raw()
+
+ * yarvtest/yarvtest.rb : add rite test scheme
+
+ * benchmark/run_rite.rb : added
+
+ * yarvcore.c, inits.c : add Init_vm()
+
+ * yarv.h : add some prototype declarations, GET_THREAD()
+
+ * eval.c : remove unused functions
+
+ * eval.c : support Kernel.eval, some schemes (same as evalc.patch)
+
+
+2005-08-15(Mon) 00:53:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarv_version.h : move configurations to yarvcore.h
+
+ * yarvcore.c : remove VALUE yarv_get_current_running_thread() and
+ add yarv_thread_t *yarv_get_current_running_thread(), ...
+
+ * yarvcore.h : yarv_thread_t#vm -> vm_value
+
+ * compile.c : fix "break from nested classes"
+
+ * yarvext/extconf.rb : use have_func instead of defined?(YARV_PACHED)
+
+ * depend : fix pass
+
+ * eval.c : change to kick VM
+
+ * version.c : fix to show yarv version
+
+ * common.mk : fix dependent
+
+ * inits.c : fix to kick Init_yarvcore
+
+
+2005-08-14(Sun) 02:05:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * README : add description
+
+ * yarvext/depend : move to topdir/depend
+
+2005-08-14(Sun) 01:50:43 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * merge yarv to ruby (prepare)
+
+ * make yarvext/ to build as extension
+
+
+2005-08-13(Sat) 09:36:26 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * evalc.patch, insns.def, compile.c : fix to support current
+ ruby HEAD.
+
+ * 0.2.3
+
+
+2005-08-08(Mon) 19:13:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h, Changes : 0.2.2
+
+
+2005-08-08(Mon) 17:17:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.h, vm.c, insns.def, yarvcore.h, yarvcore.c :
+ remove yarv_iseq_t#iseq_dt and add yarv_iseq_t#encoded.
+ use yarv_iseq_t#encoded anytime
+
+ * vm_evalbody.h, vm.h, extconf.rb, version.h :
+ support call threaded code (incomplete)
+
+
+2005-08-01(Mon) 05:26:12 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : support yield with multiple values
+
+ * compile.c : fix dynavars
+
+ * yarvcore.h : fix to mark defined method
+
+
+2005-07-31(Sun) 23:27:24 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, vm.c, insns.def : fix search object path
+
+ * compile.c : fix "for" statement
+
+ * vm_macro.def : fix rest, opt arguments
+
+
+2005-07-31(Sun) 14:52:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm_macro.def : fix block parameter
+
+ * compile.c : fix to unuse compile_data->in_ensure
+
+ * insns.def : add orphan check when return
+
+
+2005-07-31(Sun) 03:25:05 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, compile.c, yarvcore.h, insns.def :
+ support jump from rescue/ensure/class/module
+
+ * test/test_flow.rb : add tests for above fix
+
+
+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
+ are added
+
+ * insns.def : fix if unmatched size arg size to yield
+
+ * test/test_block.rb : add test for above fix
+
+ * vm.c : add th_backtrace_each and fix backtrace notation
+
+ * yarvcore.c : set top level iseq name to "<main>"
+
+
+2005-07-29(Fri) 13:20:19 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h : fix yarv_iseq_t to pass VC (cl)
+
+ * vm_dump.c : ditto
+
+ * compile.h : ditto
+
+ * insnhelper.h : ditto
+
+ * vm_evalbody.h : include 'math.h'
+
+ * insns.def, vm.c : raise error when yield without block
+
+ * vm.c : implement thread_backtrace
+
+ * vm.c, yarvsubst.c, yarv.h : implement thread_yield_light_prepare and
+ thread_yield_light_invoke
+
+ * yarvcore.c : Integer#times uses yarv specific version
+
+
+2005-07-28(Thu) 21:35:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : add another mark function for thread/stack
+
+ * vm_evalbody.h : fix register allocation for x86_64
+
+ * vm.h : use asm for tc on x86_64
+
+
+2005-07-28(Thu) 20:17:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : add mark/free message to debug gc
+
+ * insnhelper.h, insns.def, vm_macro.def : remove and
+ add new RESTORE_REGS
+
+ * vm_evalbody.h : fix register allocation
+
+
+2005-07-28(Thu) 02:00:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, etc : change VM stack structure. re-write all
+ vm functions to do it
+
+ * vm_macro.def : added
+
+
+2005-07-08(Fri) 01:36:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : don't use fmod on AMD64
+
+
+2005-07-08(Fri) 00:14:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * Changes : added
+
+
+2005-07-07(Thu) 23:54:37 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h : 0.3.0
+
+
+2005-07-07(Thu) 23:52:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * 0.2.1 : released
+
+
+2005-07-07(Thu) 23:50:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h : 0.2.1
+
+
+2005-07-07(Thu) 23:47:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb, extconf.rb : add --[enable|disable]-opt-unify-all-combination
+ and --disable-opts
+
+ * vm.h : DISPATCH_ARCH_DEPEND_WAY is only enabled on GCC 3.x
+
+
+2005-07-06(Wed) 13:20:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * depend, rb/eval.rb : add ITEMS option to benchmark rule
+
+ * benchmark/* : changed
+
+ * benchmark/other-lang/* : added
+
+
+2005-07-04(Mon) 04:02:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h. yarvcore.c : add idDIV, idMOD, idEq, idLength
+
+ * compile.c, insns.def : add specialized insn for above method id
+
+ * test/test_bin.rb : add tests for above
+
+
+2005-07-03(Sun) 20:31:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, yarvcore.h : remove cYarvThrowObject (unused)
+
+ * yarvcore.c, yarvcore.h, insns.def :
+ thread_object#stack_mark_poinetr
+
+ * depend, rb/eval.rb : BOPT, TOPT -> OPT
+
+
+2005-07-03(Sun) 13:53:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, compile.h : INSN_OBJECT, LABEL_OBJECT -> INSN, LABEL,
+ ISEQ_LINK_ELEMENT, ISEQ_LINK_ANCHOR -> LINK_ELEMENT, LINK_ANCHOR,
+ and some fixes
+
+ * tmpl/optinsn.inc.tmpl : ditto
+
+ * yarvcore.c, yarvcore.h : remove label_object, insn_object
+ prepare_iseq_build, cleanup_iseq_build are added
+
+ * insns.def : remove unused variable from send
+
+
+2005-07-02(Sat) 04:19:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : add GC protect for opt_aset
+
+
+2005-07-02(Sat) 03:49:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb : add option -fno-reorder-blocks to vm.asm rule
+
+ * insns.def : fix opt_aset bugs
+
+ * test/test_bin.rb : add tests for aset, aref
+
+
+2005-07-02(Sat) 03:05:12 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run.rb : fix output
+
+ * vm_evalbody.h : add register for x86_64
+
+ * rb/asm_parse.rb : fix to shor size and length
+
+
+2005-07-02(Sat) 02:56:31 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : move specialized instruction point (new_insn_send)
+
+ * insns.def : add opt_aref, opt_aset
+
+
+2005-07-01(Fri) 11:04:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.h : fix to pass VALUE type to new_insn_body
+
+ * insnhelper.h : add cast
+
+ * compile.c : fix getdynamic argument (0 == Qfalse -> I2F(0))
+
+
+2005-06-30(Thu) 23:34:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/eval.rb : add and fix some rules
+
+ * rb/insns2vm.rb : generate all
+
+ * benchmark/run.rb : add -r (ruby only) option
+
+
+2005-06-30(Thu) 23:25:23 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * tmpl/vmtc.inc.tmpl : add const prefix
+
+ * /rb/asm_parse.rb, extconf.rb : added and make assembler analised output
+
+ * opt_operand.def : add send operands unification
+
+ * insnhelper.h : add HEAP_CLASS_OF(obj)
+
+ * insns.def : fix opt_plus, opt_ltlt
+
+ * vm_evalbody.h : move _tag
+
+ * benchmark/run.rb : fix file select
+
+
+2005-06-30(Thu) 06:07:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb : add collect-usage-analysis option
+
+ * opt_operand.def, opt_insn_unif.def : add some rules
+
+
+2005-06-29(Wed) 23:28:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, extconf.rb, vm.h, compile.c :
+ DISPATCH_DIRECT_THREADED_CODE, DISPATCH_THREADED_CODE
+ -> OPT_DIRECT_THREADED_CODE, OPT_INDIRECT_THREADED_CODE.
+ if at least one of then is defined, OPT_THREADED_CODE is defined
+
+ * benchmark/* : fix name and parameters
+
+ * rb/eval.rb : added for YARV evaluation
+
+
+2005-06-29(Wed) 16:16:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run.rb : fix output format
+
+ * call_cfunc.inc -> call_cfunc.h
+
+ * vm.h : add sign by asm statement
+
+
+2005-06-28(Tue) 22:28:40 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : fix method search
+
+
+2005-06-28(Tue) 22:26:34 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb : fix options
+
+
+2005-06-28(Tue) 21:50:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run.rb : fix output format
+
+
+2005-06-28(Tue) 21:34:54 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * depend : add option TOPT to test rules
+
+ * benchmark/run.rb : fix output format
+
+
+2005-06-28(Tue) 21:15:54 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix opt_case_dispatch instruction
+
+ * benchmark/run.rb : output all usertimes when exit benchmark
+
+
+2005-06-28(Tue) 20:35:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb, compile.c, tmpl/optinsn.inc.tmpl, vm.c :
+ change extconf options
+
+2005-06-28(Tue) 13:20:59 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run.rb : add -y, --yarv-only option
+
+ * depend : add BOPT to tbench rule
+
+
+2005-06-27(Mon) 23:31:12 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * depend : add gdb rule
+
+ * vm.h : use inline assembler for x86 (to support gcc 3.4.x)
+
+
+2005-06-27(Mon) 20:04:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, compile.c, disasm.c : remove unused variables
+
+ * vm.h, insnhelper.h, debug.h : fix to reduce warning
+
+ * vm.c, vm_dump.c : move VM state dump (debug) functions to vm_dump.c
+
+ * depend : adde reconf rule
+
+ * insnhelper.h :
+
+ * vm_evalbody.inc : rename to vm_evalbody.h
+
+
+2005-06-27(Mon) 16:50:31 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns2vm.rb : fix generating unif insn
+
+ * compile.c : add useless pop/swap insn elimination with stack caching
+
+ * depend : remove compiled.o dependency
+
+
+2005-06-26(Sun) 14:06:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run.rb : use tmpfile instead of popen
+
+ * rb/insns2vm.rb : fix generating insn unification logic
+
+ * opt_insn_unif.def : add some unification rules
+
+ * compile.c : add verify_list function and fix unification logic
+
+
+2005-06-22(Wed) 12:58:26 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, yarvcore.c, insns.def, compile.c : add mult optimization
+
+ * test/test_bin.rb : add test_fact
+
+
+2005-06-21(Tue) 22:34:07 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, compile.[ch], tmpl/optinsn.inc.tmpl, rb/insns2vm.rb :
+ change data structure (don't use Ruby's array to represent a
+ instruction sequence)
+
+ * disasm.c : add separator
+
+
+2005-06-14(Tue) 07:48:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support "for" statement
+
+ * test/test_block.rb : add test for above
+
+ * yarvcore.[ch] : add global id idEach
+
+
+2005-06-08(Wed) 22:30:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : add if/unless(L1) jump (L2) :L1 => unless/if(L2)
+ optimize (condition reversal) and fix typo
+
+
+2005-06-07(Tue) 08:29:41 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : fix to remove compiler warning
+
+ * version.h : 0.2.1
+
+
+2005-06-07(Tue) 08:16:22 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h : iseq_link_element changed to double linked list
+
+ * disasm.c : support dump struct iseq_link_element
+
+ * compile.c : use double linked list instead of array
+ for intermediate representation
+
+
+2005-06-06(Mon) 15:38:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, yarvcore.c : add link structure to insn and label object
+
+ * compile.h, compile.c : remove some variables in function top scope
+ of iseq_compile_each and some optimization (now working)
+
+
+2005-06-04(Sat) 16:12:59 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix previous commit
+
+
+2005-06-04(Sat) 15:56:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix stack caching (after jump state)
+
+
+2005-06-04(Sat) 09:12:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix some point for previous commit
+
+
+2005-06-04(Sat) 07:31:21 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : optimize case/when statement
+ (dispatch on constant time)
+
+ * yarvcore.h, disasm.c, rb/insns2vm.rb : fixed for above
+ (CDHASH)
+
+ * test/test_syn.rb : add test for above
+
+
+2005-06-04(Sat) 03:41:29 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, yarvcore.c : add some temporary variable test
+ (it'll be vanished)
+
+ * compile.c : NODE_CASE optimize (use topn instead of dup/swap)
+
+
+2005-06-03(Fri) 00:54:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : apply flow optimization for while/until statement
+
+
+2005-03-04(Fri) 19:34:32 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb : fix category (comment)
+
+ * depend : remove space betweeen target name and colon
+
+
+2005-03-04(Fri) 15:55:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * tmpl/yarvarch.ja : fix typo
+
+
+2005-03-04(Fri) 13:30:19 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * depend : add a rule for jitcompile.o
+
+ * vm.h : fix a macro argument
+
+ * version.h : 0.2.0
+
+
+2005-03-03(Thu) 08:35:14 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb : remove vm_evalbody.inc call_cfunc.inc from clean target
+
+
+2005-03-03(Thu) 00:54:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * tmpl/insns.inc.tmpl : fixed typo
+
+ * insns.def : store th->pc to current pc
+
+
+2005-03-03(Thu) 00:31:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * tmpl/yarvarch.ja, doc/yarv.rb : write current architecture of yarv
+
+
+2005-03-01(Tue) 13:50:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c (yarvcore_eval_parsed) : added
+ (separeted from yarvcore_eval)
+
+ * yarvcore.c, compile.c : iseq_translate_direct_threaded_code
+ is moved to compile.c
+
+ * depend : add rule for yasmdata.rb
+
+ * rb/yasm.rb : support top-level and method-level assemble
+
+
+2005-02-26(Sat) 08:09:57 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb, compile.c, vm.h : change type long to OFFSET
+
+ * tmpl/yasmdata.rb.tmpl : added
+
+ * rb/insns2vm.rb : add yasmdata_rb method
+
+ * rb/yasm.rb : fix some interface (incomplete)
+
+ * compile.c : iseq_setup added
+
+ * yarvcore.c : YARVCore::InstructionSequence::Instruction#make added
+
+
+2005-02-24(Thu) 07:45:37 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/yasm.rb : added
+
+
+2005-02-24(Thu) 01:13:33 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : remove useless statements
+
+
+2005-02-24(Thu) 00:46:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb (InsnInfo) : add @is_sc attr and remove
+ is_sc method
+
+ * compile.c : fix NODE_CASE/NODE_WHEN bug (cond at 'when'
+ must not be popped)
+
+ * compile.c : support NODE_OP_ASGN1 to &&= and ||=
+
+ * test/test_bin.rb : add tests for above
+
+
+2005-02-23(Wed) 09:17:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, yarvcore.c : thread_svar added and fix svar location
+
+
+2005-02-21(Mon) 08:38:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h : make type "struct iseq_compile_data"
+
+ * yarvcore.h : iseq_object#insn_info_ary to iseq_object#insn_info_tbl
+
+
+2005-02-21(Mon) 05:24:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c (compile_string) : remove null check of node
+
+
+2005-02-19(Sat) 03:52:45 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h : 0.1.1
+
+
+2005-02-18(Fri) 20:57:18 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, yarvcore.c : add idLTLT, idMethodMissing
+
+ * compile.c : suopport lval (or others) block parameter
+
+ * test/test_block.rb : add tests for above
+
+ * insns.def (send) : support method_missing
+
+ * test/test_method.rb : add tests for above
+
+ * insns.def : opt_ltlt and
+
+
+2005-02-18(Fri) 08:54:40 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/runc.rb : added
+
+ * benchmark/contrib/pentomino.rb : added opt_ltlt
+ and Float, String plus specialization
+
+
+2005-02-18(Fri) 07:49:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : remove debug print
+
+ * rb/aotcompile.rb : skip if yarvcore.so is not created
+
+
+2005-02-18(Fri) 06:46:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix block passing
+ and block argument
+
+
+2005-02-18(Fri) 05:52:41 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : thread_get_ev_const, thread_get_ev_defined is added
+ (separated from insns.def)
+
+ * insnhelper.h : GET_EV_KLASS(klass) is added
+ (separated from insns.def)
+
+ * yarvcore.h, insns.def, compile.c : support defined? expression (limited)
+
+ * test/test_syn.rb : tests for above is added
+
+ * compile.c, insns.def : support block passed method dispatch
+
+ * test/test_method.rb : tests for above is added
+
+ * compile.h : CALL_ARGS_SPLAT is removed
+
+
+2005-02-16(Wed) 13:32:37 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * disasm.c : fix ID to String method
+
+ * compile.c : NODE_SUPER, NODE_ZSUPER check 'poped'
+ and NODE_RETURN check outer type
+ and NODE_DREGX_ONCE supported (temporarily)
+
+ * test/test_syn.rb : add a test
+
+ * test/test_jump.rb : add a test
+
+
+2005-02-16(Wed) 06:07:41 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.[hc] : use Symbol instead of Fixnum to represent ID
+
+ * rb/insns2vm.rb : add attr_reader :insns, :insn_map
+
+ * vm.h, rb/insns2vm.rb : END_INSN have one arg
+
+ * jitcompile.c : jit compiler framework (experimental)
+
+ * rb/aotcompile.rb : refactoring
+
+ * compiled.c : add constant pool
+
+ * vm_evalbody.inc, call_cfunc.inc, vm.c : separeted from vm.c
+
+ * insns.def : fix return val
+
+ * depend : add rules for compiled.o
+
+
+2005-02-14(Mon) 13:09:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insnhelper.h, yarvcore.h: move YARV_METHOD_NODE to yarvcore.h
+
+ * yarvcore.h : add 2 members jit_compiled and iseq_orig
+ to struct iseq_object
+
+ * yarvcore.c : add yarv_jitcompile and global function jitcompile
+
+ * insns.def : insn opt_call_native_compiled added
+
+ * jitcompile.c : added
+
+
+2005-02-12(Sat) 05:38:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def (putstring) : fixed to duplicate string object
+
+ * rb/insns2vm.rb, tmpl/optunifs.inc.tmpl, compile.c : support
+ instructions unification (aka super instruction)
+
+ * opt_insn_unif.def : added for above
+
+ * benchmark/bm_unif1.rb : added to measure efficiency of unification
+
+ * depend : fixed for above
+
+ * extconf.rb : add option --(enable|disalbe)-opt-insns-unification
+
+
+2005-02-11(Fri) 12:14:39 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, vm.c, insns.def : permit to access svar from
+ cfunc environment
+
+ * test/test_method.rb : add tests for above
+
+
+2005-02-09(Wed) 19:31:06 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * ite.rb : added (ruby -rite [script file])
+
+
+2005-02-09(Wed) 02:25:43 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.[hc] : add member compile_data (hash) to iseq_object
+
+ * compile.c, yarvcore.h : check label is already set
+
+ * compile.c, extconf.rb : support __goto__ and __label__ statement
+
+
+2005-01-25(Tue) 12:49:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_block.rb : add break test to test_times
+
+
+2005-01-25(Tue) 03:34:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb : check ruby version if yarv patch is applied or not
+
+ * evalc.patch : fixed for rb_call_super and above check
+
+
+2005-01-25(Tue) 03:21:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb : refactoring (mainly, make InsnsDef::InsnInfo
+ to represent each instruction information)
+
+ * depend, rb/makedocs.rb : fixed for above
+
+ * yarvcore.c (thread_call_super) : added
+
+ * vm.c (thread_call_super) : added
+
+ * vm.h : add struct cmethod_info
+
+ * insns.def, vm.c : use cmethod_info to represent C method info
+
+ * insns.def : use iseq_object#klass_nest_stack
+ to search super/zsuper's class
+
+ * prosym.rb : removed
+
+ * ToDo : write todo things on wiki
+
+
+
+2005-01-18(Tue) 23:44:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run.rb : check ENV['RUBY'] to use ruby binary
+
+
+2005-01-10(Mon) 08:44:40 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h : 0.1.0
+
+
+2005-01-09(Sun) 22:01:29 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * repository : svn propset svn:eol-style native *.c *.h tmpl/*.tmpl
+
+
+2005-01-09(Sun) 21:48:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : FREE_UNLESS_NULL, MARK_UNLESS_NULL macros are added
+
+ * yarvcore.c : some insn/label methods are added
+
+ * yarvcore.h : add structure menber "insns_ary" to iseq_object
+
+ * vm.c, insns.def (thread_eval_body) : return values with throw
+
+ * prosym.rb : added
+
+ * insns.def : add YARV_AOT_COMPILED and some procedure
+
+ * depend : add compiled.c
+
+ * compiled.c : added to build compiled Ruby program (C source)
+ by AOT compiler
+
+ * rb/aotcompile.rb : AOT compiler
+
+ * aotct.rb, rb/aotctest.rb : test and benchmark AOT compiler
+
+ * rb/allload.rb : added
+
+
+2005-01-09(Sun) 08:30:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c (yarv_yield_values) : added
+
+ * vm.c (thread_call0) : change interface. substitute rb_call0 in
+ yarv environment
+
+ * yarvcore.c (yarv_call0) : fix for above
+
+ * yarvcore.c (yarv_call0_cfunc) : removed
+
+ * yarvcore.c : change passing items for yarv_setup
+
+ * evalc.patch : fix for above
+
+ * benchmark/bm_lists.rb : fix (unsupport block passing)
+
+ * benchmark/run.rb : use full path to ruby
+
+ * insns.def (yield): raise error if argc > expected argc
+
+
+2005-01-08(Sat) 16:07:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb : add descrioptions
+
+ * compile.c : fix bugs (getinlinecache operands)
+
+ * yarvcore.c : initial value of yarvGlobalStateVersion
+ to 1
+
+
+2005-01-08(Sat) 14:39:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, vm.c, evalc.patch : support making backtrace
+ (incompatible with current ruby interpreter)
+
+
+2005-01-08(Sat) 11:25:46 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * evalc.patch : commit for previous commit change
+
+ * yarvcore.h, compile.c, insns.def : MC to IC (inline cache),
+ and changed to using IC by set/getinlinecache
+
+
+2005-01-08(Sat) 10:04:33 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : add global variable sym[IC]FUNC
+
+ * yarvcore.c (yarv_iterate, yarv_call0_cfunc) : added
+ (each called from rb_iterate, rb_call0 with NODE_CFUNC)
+
+ * vm.c (stack_dump_raw) : fixed to prints more detail
+
+ * vm.c (stack_dump_th, stack_dump_thobj) : added to
+ dumps thread_object states (for VALUE, struct pointer)
+
+ * vm.c (thread_dump_regs) : added
+
+ * vm.c (thread_call0, thread_call0_cfunc, thread_invoke_yield,
+ thread_invoke_yield_cfunc), insns.def (yield, send) :
+ fixed, added to support IFUNC
+
+ * vm.c, yarvcore.c, insns.def : change type purpose
+ thread_object#block_ptr (it holds IFUNC block information,
+ so this type was changed to 'NODE *')
+
+ * vm.c (stack_dump_each) : fixed for above
+
+ * test/test_block.rb (test_ifunc) : test for above
+
+ * vm.c (get_block_objec, thread_make_env_object) : fixed bugs
+
+ * test/test_bin.rb (test_xstr) : remove `ls` test
+
+
+2005-01-06(Thu) 21:35:18 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarv : trying to support NODE_IFUNC (rb_iterate)
+
+
+2005-01-05(Wed) 06:50:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, insns.def, disasm.c, rb/insns2vm.rb, compile.[ch] :
+ support inline method cache
+
+ * extconf.rb : add -*-inline-method-cache (default: enable)
+
+ * test/test_method.rb : add a test for above
+
+ * benchmark/bm_poly_method.rb : added
+
+ * yarvcore.c : add option string
+
+
+2005-01-04(Tue) 17:15:41 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, compile.c : add compile_array and duparray insn
+ to optimize only literal array creation
+
+ * benchmark/bm_array.rb : added
+
+
+2005-01-04(Tue) 10:02:40 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * README : fix version
+
+
+2005-01-04(Tue) 09:57:25 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * ToDo : reflect current status
+
+
+2005-01-04(Tue) 09:43:54 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_VALUES, NODE_ARGSCAT, NODE_SPLAT
+
+ * test/test_massign.rb : add tests for above
+
+ * benchmark/bm_swap.rb : added
+
+
+2005-01-04(Tue) 06:25:45 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.h : COMPILE_ERROR break contol (instead of return)
+
+ * compile.c : support NODE_MASGN
+
+ * insns.def : change expandarray for massign and add topn insn
+
+ * test/test_massign.rb : added
+
+
+2005-01-03(Mon) 21:20:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : store block when create proc
+
+ * test/test_proc.rb : add a test for above change
+
+ * yarvcore.c : add global function "once"
+
+
+2005-01-02(Sun) 00:40:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bm_super.rb : fix bug (remove infinite loop)
+
+
+2005-01-01(Sat) 23:45:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bm_z?super.rb : added
+
+
+2005-01-01(Sat) 23:37:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bmx_so_object.rb : rename to benchmark/bm_so_object.rb
+
+
+2005-01-01(Sat) 23:19:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_OP_ASGN2, NODE_OP_ASGN_AND, NODE_OP_ASGN_OR,
+ NODE_SUPER, NODE_ZSUPER, NODE_MATCH
+
+ * insns.def : support super, zsuper (currently, super can't
+ handle with block)
+
+ * test/test_bin.rb : add test for op_asgin2, op_assgin_and/or
+
+ * test/test_class.rb : add test for super, zsuper
+
+
+2005-01-01(Sat) 20:39:29 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_MATCH
+
+ * yarvcore.c : fix yarv_svar bug (fix condition boundary)
+
+ * insnhelper.h : save cfp/lfp/dfp vars to thread_object (th)
+
+
+2005-01-01(Sat) 20:03:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h : 0.0.1
+
+ * yarvcore.h : add idIntern declaration
+
+ * insns.def : add getspecial, setspecial.
+ implement getclassvariable, setclassvariable.
+ store lfp before reg match (opt_regexpmatch1)
+
+ * compile.c : support ditto, flipflop
+
+ * yarvcore.c : support svar
+
+ * test/test_syn.rb : add test for flipflop
+
+ * test/test_bin.rb : add test for dsym, cvar, backref
+
+
+2005-01-01(Sat) 09:09:32 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : add getspecial insn
+
+ * compile.c : support NODE_NTH_REF, NODE_BACK_REF
+
+
+2005-01-01(Sat) 06:53:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, compile.c : support alias, undef
+
+ * test/test_method.rb : test for above
+
+ * rb/insns2vm.rb : fix enbug
+
+
+2005-01-01(Sat) 06:00:32 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_jump.rb : add test (next with value)
+
+ * yarvcore.h, yarvcore.c, compile.c, compile.h :
+ raise compile error exception instead of rb_bug
+
+ * yarvcore.c, evalc.patch : support "require"
+
+ * test.rb : restore $" after evaluation with ruby
+
+ * rb/insns2vm.rb : remove unnecesary each
+
+
+2004-12-17(Fri) 18:56:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix newhash
+
+
+2004-12-15(Wed) 13:29:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : add version string
+
+ * compile.c : fix rescure clause bug
+
+
+2004-12-14(Tue) 22:46:30 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : add reput insn
+
+ * vm.h : show stack cache registers when stack dump
+
+ * rb/insns2vm.rb, compile.c : fix stack caching bugs
+
+
+2004-12-14(Tue) 00:51:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns2vm.rb, compile.c, tmpl/opt_sc.inc.tmpl : fix bugs
+
+ * rb/mixc-asm.rb : added
+
+
+2004-12-14(Tue) 00:17:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, yarvcore.c, compile.c : fix SC bugs
+ (SC state management)
+
+ * extconf.rb : add option -[enable|disable]-opt-stack-caching
+
+ * insns2vm.rb : accept CPPFLAGS options
+
+ * vm.c : support restrore register for pc
+
+
+2004-12-13(Mon) 16:53:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb : add macro INSN_IS_SC()
+
+
+2004-12-11(Sat) 10:51:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, compile.c : support singleton method definition
+
+ * test/test_method.rb : add test for above
+
+
+2004-12-11(Sat) 03:17:54 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/*.rb : modify
+
+ * extconf.rb : add $cleanfiles
+
+
+2004-12-08(Wed) 13:01:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : change to disable stack caching
+
+
+2004-12-07(Tue) 19:37:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.rb : add default after
+
+ * insns.def : fix to work on stack caching
+
+
+2004-12-07(Tue) 15:07:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * depend : add some dependency to *.inc files
+
+ * vm.c : add "register" and asm("regname") descriptor
+
+ * rb/insns2vm.rb, compile.c : add stack caching support
+
+ * tmpl/opt_sc.inc.tmpl : added to above change
+
+ * rb/makedocs.rb : fix file path
+
+ * extconf.rb : fix option selection
+
+
+2004-12-06(Mon) 11:20:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * extconf.rb : add vm.asm target if compiler is gcc
+
+
+2004-12-06(Mon) 09:56:24 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.h : rename method_frame's member block to block_ptr
+
+ * extconf.rb : add "-fno-crossjumping" option when compiler
+ is gcc
+
+ * opt_operand.def : add unification insn send
+
+ * rb/insns2vm.rb : define symbol instead of declare const
+ variable (for more optmize on VC)
+
+ * insns.def : move enter point in send
+
+
+2004-12-06(Mon) 04:53:51 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, opt_operand.def, rb/insns2vm.rb, depend :
+ support operand unification
+
+
+2004-12-05(Sun) 03:16:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, insns.def : speed up throw/catch scheme
+
+
+2004-12-05(Sun) 01:47:05 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : fix catch handler bugs
+
+ * test/test_jump.rb : test_complex_jump added
+
+
+2004-12-03(Fri) 20:39:05 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/contrib/mcq.rb : added
+ (from URABE Syouhei)
+
+
+2004-12-03(Fri) 20:35:28 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : support break in rb_yield block
+
+
+2004-12-03(Fri) 14:26:35 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support block local variable in current
+ ruby specification (patche from Kent Sibilev)
+
+ * insns.def : support attr_* (patch from Kent Sibilev)
+
+
+2004-12-02(Thu) 21:04:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * opt_operand.def : added
+
+
+2004-12-02(Thu) 13:20:41 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c, vm.h, vm.c, insns.def, insnhelper.h, yarvutil.rb :
+ add usage analisys framework
+
+ * disasm.c : insn_operand_intern to separate function
+
+ * benchmark/run.rb : run each benchmark on another process
+
+
+2004-12-01(Wed) 10:26:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : yield check block is given
+
+ * benchmark/bm_lists.rb : rename to bmx_lists.rb
+ (because it's not work ... bug?)
+
+ * insns.def : opt_* support other type calc
+
+
+2004-11-30(Tue) 16:14:54 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bm_so_array.rb : added
+
+ * benchmark/bm_so_matrix.rb : added
+
+
+2004-11-30(Tue) 14:11:30 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/getrev.rb : added
+
+ * yarvcore.c : add YARVCore::REV, YARVCore::DATE constant
+
+
+2004-11-30(Tue) 13:05:42 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_OP_ASGN1 (incomplete)
+
+ * insns.def : add dupn
+
+
+2004-11-30(Tue) 08:52:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h : 0.0.0.f
+
+
+2004-11-30(Tue) 08:43:59 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_class.rb : add test_initialize and test_to_s
+
+ * yarvsubst.c : use rb_funcall instead of yarv_funcall
+
+ * evalc.patch : fix ruby's patch
+
+ * benchmark/bm_so_*.rb : change naming rule. "bm_so_*" from
+ language shootout
+
+ * depend : tbench target item is ITEM env val (default: bmx_temp)
+
+ * vm.c : show raw address if environment is in heap at dumping stack trace
+
+ * vm.c : thread_call0 added
+
+ * vm.c : fix thread_yield_light_invoke
+
+ * yarv.h, yarvcore.c : remove yarv_funcall
+
+
+2004-11-29(Mon) 11:37:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test/test_proc.rb : add test test_nestproc
+
+ * yarvsubst.c : comment out yarv_Array_each
+
+ * insns.def : restore lfp/dfp after call_cfunc
+
+ * vm.c : fix stack dump routine
+
+ * vm.c : impliment thread_funcall (temporarily)
+
+ * yarv.h : add IS_YARV_WORKING(), SET_YARV_START(), SET_YARV_STOP()
+
+ * yarvcore.c : remove check with yarv_in_work
+
+ * evalc.patch : added
+
+
+2004-11-27(Sat) 00:19:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.c : free -> ruby_xfree
+
+
+2004-11-26(Fri) 02:11:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm,c : fix bug
+
+
+2004-11-22(Mon) 11:19:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/bm_ackermann.rb, bm_proc.rb, bm_simpleiter.rb,
+ bm_so_exception.rb, bm_wc.rb, wc.input added
+
+
+2004-11-22(Mon) 02:31:56 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_proc.rb : add some test
+
+ * yarvcore.c, vm.c : support yield in C method (as rb_yield)
+
+ * vm.c (thread_yield_light_(prepare|invoke)) : support lightweight
+ yield
+
+ * yarv.h : added
+
+ * yarvcore.c, yarv.h : support yarv_is_working, yarv_block_given_p,
+ yarv_yield, yarv_funcall (only dummy function)
+
+ * vm.c : thread_eval_body changed return value
+
+ * yarvsubst.c : added and add yarv_Integer_times, yarv_Array_each
+
+ * yarvcore.h : block_ptr is added to struct thread_object
+
+ * insns.def : pass block when C method call
+
+ * insnhelper.h : add GET_ISEQOBJ(cfp) macro
+
+
+2004-11-21(Sun) 07:25:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c : support Proc#call
+
+ * test/test_proc.rb : added
+
+
+2004-11-19(Fri) 18:04:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def, vm.c : support creating Proc object
+
+
+2004-11-15(Mon) 14:19:27 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def (send) : use clear_local_size to specify
+ clear local table vars.
+
+ * insns.def : block represent data shares lfp, dfp with frame data
+
+
+2004-11-13(Sat) 18:19:41 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, insns.def : add VM_CALL_ARGS_SPLAT_BIT and
+ VM_CALL_ARGS_BLOCKARG_BIT
+
+ * compile.c, compile.h : add ADD_SEND, ADD_SEND_R
+
+
+2004-11-10(Wed) 08:26:25 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * add "vm_" prefix to (block_object, proc_object, env_object)
+
+
+2004-11-03(Wed) 15:52:14 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, yarvcore.c, disasm.c, compile.c, insns.def, vm.c :
+ fix to move x86_64 (illegal cast, etc)
+
+
+2004-11-01(Mon) 04:45:54 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, compile.c, debug.c, version.h :
+ redesgin gc debug scheme (GC_CHECK())
+
+ * yarvcore.c : mark iseqobj->current_block on GC
+
+ * insns.def, compile.c : last "throw" in ensure/rescue block
+ use operand throwobj and before this insn, use "getdynamic 0, 1"
+
+ * benchmark/bm_temp.rb : move to benchmark bmx_temp.rb
+
+ * depend : change some targets
+
+
+2004-10-25(Mon) 19:57:58 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : push exception iseq to iseqobj->iseq_mark_ary
+ to mark for GC
+
+
+2004-10-10(Sun) 16:25:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : remove $_, $' area from method local frame
+ and provide that's special method local variables pointer(LFP[-1])
+
+ * disasm.c : change environment showing format
+
+ * yarvcore.(h|c) : add YarvProc, YarvEnv
+
+ * yarvcore.h : add arg_block field to iseq_object
+ and init -1 as default value
+
+
+2004-09-30(Thu) 19:50:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : support passing splat argument
+
+ * compile.c, insns.def : support rest argument
+
+ * compile.c, insns.def : support optional argument initializer
+
+ * test/test_method.rb : add tests for above
+
+
+2004-09-29(Wed) 10:50:03 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix rescue clause popped
+
+ * benchmark/bm_random.rb : move to benchmark/bmx_random.rb
+
+
+2004-09-29(Wed) 01:25:35 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * many many files: change stack frame design
+
+
+2004-09-16(Thu) 08:51:37 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, yarvcore.h : support 'return' from method
+ in ensure clause
+
+
+2004-09-13(Mon) 21:56:40 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support inline cache constant access
+ on NODE_COLON2, NODE_COLON3
+
+ * depend : add 'vtest' rule(verbose test)
+
+
+2004-09-13(Mon) 10:58:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, yarvcore.h : support redo/next/break in
+ while/until
+
+
+2004-09-13(Mon) 08:50:19 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_jump.rb : added(correctly)
+
+ * benchamark/bm_(ensure|rescue|simplereturn).rb added
+
+
+2004-09-12(Sun) 23:30:20 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_jump.rb : added
+
+ * insns.def, compile.c : add 'putnil' insn
+
+ * compile.c : use '===' when rescue check
+
+ * insns.def : remove 'rescuecheck' insn
+
+ * compile.c : support retry in begin/rescue clause
+
+ * ToDo : added
+
+
+2004-09-08(Wed) 12:34:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvcore.h, yarvcore.c : add idThrow*
+
+ * insns.def, compile.c, vm.c : support retry, break,
+ next, redo, return(imcomplete)
+
+
+2004-09-03(Fri) 13:40:08 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : add nop after rescue body
+
+ * insns.def, vm.c : support stack rewind when thrown
+
+
+2004-09-01(Wed) 17:31:01 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_exception.rb : added
+
+
+2004-09-01(Wed) 13:15:14 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, insns.def : implementing exception handling
+
+
+2004-09-01(Wed) 00:18:54 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : add 'throw' insn
+
+ * compile.c : support 'rescue' and 'ensure' clause
+
+ * yarvcore.c, yarvcore.h : add 'catch_table' to iseq_struct
+
+
+2004-08-30(Mon) 19:06:12 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.h : NEW_ISEQOBJ don't pass self as parent
+
+ * compile.c : use NEW_CHILD_ISEQOBJ explicitly
+
+
+2004-08-29(Sun) 21:09:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : trying to implement rescue/ensure
+
+ * insns.def : fix yield bug(lfp, dfp link)
+
+
+2004-08-28(Sat) 13:52:15 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix dvar bug
+
+ * test/test_block.rb : add test
+
+ * insns.def, insnhelper.h : remove unused source code
+
+
+2004-08-28(Sat) 08:51:26 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_DASGN
+
+ * test/test_block.rb : add test
+
+
+2004-08-28(Sat) 08:13:04 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : support access to instance variable
+
+ * test/test_class.rb : add test of instance variable
+
+ * benchmark/bm_block.rb : added
+
+
+2004-08-28(Sat) 07:48:43 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_block.rb : fix block parameter name
+
+
+2004-08-28(Sat) 07:27:52 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c, insns.def : support method call with block
+ and yield and add some functions
+
+ * compile.c, insns.def : support dynavars accessor
+
+ * test/test_block.rb : added
+
+ * vm.c : fix block parameter stack dump
+
+
+2004-08-27(Fri) 23:56:47 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c(iseq_compile) : remove parameter iseqtype
+ (this information can access via self)
+
+2004-08-27(Fri) 17:13:35 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_bin.rb : add test(absolute path constant)
+
+ * yarvcore.h, compile.c(iseq_compile) : change parameter
+
+ * insns.def(classdef) : fix bug
+
+
+2004-08-27(Fri) 04:53:13 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : support setconstant, getconstant, classdef,
+ moduledef
+
+ * vm.h : fix debug levels and so on
+
+ * vm.h : foo_WORD -> foo_WC
+
+ * test/test_class.rb : added
+
+
+2004-08-25(Wed) 17:51:50 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix getconstant/setconstant/classdef
+
+
+2004-08-25(Wed) 14:27:10 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * debug.[ch] : added
+
+ * compile.c, disasm.c : use debug interface
+
+ * compile.c : support some nodes
+
+ * compile.c, rb/insns2vm.rb : remove TS_CPATH
+
+ * insns.def : modify classdef/moduledef/singletonclassdef
+ and add popcref
+
+ * and others...
+
+
+2004-08-18(Wed) 20:16:45 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix case/when statement with empty else clause
+
+ * insns.def : enable compile
+
+ * yarvcore.h : add class search path scheme
+
+ * test/test_syn.rb : add switch/case test case
+
+ * tmpl/yarvarch.ja : update documents
+
+
+2004-05-22(Sat) 01:30:44 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvutil.rb : add eval_in_wrap
+
+ * test/test_*.rb : change to use eval_in_wrap
+
+
+2004-05-20(Thu) 02:50:32 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * support global variables
+
+ * benchmark/bm_*.rb : add some benchmarks
+
+ * compile.c : support NODE_ATTRASGN
+
+ * compile.c : add debugi(...)
+
+
+2004-05-19(Wed) 23:19:38 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * test/test_method.rb : added
+
+
+2004-05-19(Wed) 22:56:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : fix typo
+
+ * benchmark/run.rb : sort benchmark order by filename
+
+ * extconf.rb : use --enable/disable-xxx
+
+ * version.h : ditto(don't touch to change yarv options)
+
+
+2004-05-19(Wed) 21:18:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * yarvutil.rb : added
+
+ * test.rb, test/*, benchmark/run.rb : use yarvutil.rb
+
+ * version.h : USE_OPTIMIZED_REGEXP_MATCH added
+
+ * yarvcore.h : add idEqTilde
+
+ * yarvcore.c(yarvcore_parse, yarvcore_eval) : require file and line
+ parameter
+
+ * test/test_bin.rb : add regexp test
+
+ * benchmark/bm_regexp.rb : added
+
+
+2004-05-19(Wed) 13:57:31 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : add compile_dstr(self, node)
+
+ * compile.c : support NODE_MATCH2, NODE_MATCH3, NODE_DXSTR
+
+ * insns.def : add toregexp
+
+
+2004-05-18(Tue) 10:12:20 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_XDSTR
+
+ * test/test_bin.rb : add test for above change
+
+
+2004-05-18(Tue) 09:46:33 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def(send) : store regs before call_cfunc
+
+
+2004-05-18(Tue) 08:55:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : support NODE_DSTR, NODE_EVSTR
+
+ * compile.c : support NODE_XSTR
+
+ * insns.def : add tostring operation
+
+ * rb/makedocs.rb : fix directory path
+
+ * depend : add tbench rule
+
+ * yarvcore.h : add 'exten ID idBackquote'
+
+
+2004-05-18(Tue) 00:09:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h : add USE_OPTIMIZED_BASIC_OPERATION
+
+ * yarvcore.h(struct thread_object) : add 'VALUE stat_insn_usage'
+
+
+2004-05-17(Mon) 11:28:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * version.h, insns.def, yarvcore.c : add FAKE_INLINE_METHOD_CACHE
+
+
+2004-05-17(Mon) 09:05:53 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * compile.c : fix generating opt_* insn process
+
+
+2004-05-17(Mon) 08:58:49 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/(bm_tarai.rb, bm_fib.rb) : added
+
+
+2004-05-17(Mon) 08:20:12 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/(bm_tak.rb, bm_reccount.rb) : added
+
+ * insns.def : test method cache(incomplete)
+
+ * insns.def : add expandarray insn
+
+ * yarvcore.c(iseq_init) : add parameter 'parent'
+
+
+2004-05-17(Mon) 01:49:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * benchmark/run.rb, bm_factorial.rb, bm_whileloop.rb : added
+
+ * insns.def(send) : set id to ruby_frame->orig_func
+
+ * check behavior on mswin32 and cygwin
+
+ * insns.def(send) : check stack overflow
+
+
+2004-05-16(Sun) 08:00:55 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * change frame structure(debugging)
+
+
+2004-05-14(Fri) 15:06:02 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns2vm.rb : support file name arguments
+
+
+2004-05-14(Fri) 04:33:09 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def : support (easy) constant
+
+
+2004-05-12(Wed) 01:51:48 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * rb/insns2vm.b : set directory prefix
+
+ * disasm.c : fix bug
+
+
+2004-05-12(Wed) 00:00:17 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.h, compiler.h, version.h : move *DEBUG defs to version.h
+
+
+2004-05-11(Tue) 23:00:11 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * vm.h, version.h, yarvcore.h : move gcc ver check to version.h
+ and include version.h from yarvcore.h
+
+
+2004-05-11(Tue) 19:16:26 +0900 Koichi Sasada <ko1@atdot.net>
+
+ * 0.0.0.d : imported
+
+
+Local variables:
+add-log-time-format: (lambda ()
+ (let* ((time (current-time))
+ (diff (+ (cadr time) 32400))
+ (lo (% diff 65536))
+ (hi (+ (car time) (/ diff 65536))))
+ (format-time-string "%Y-%m-%d(%a) %H:%M:%S +900" (list hi lo) t)))
+indent-tabs-mode: t
+tab-width: 8
+end:
@@ -11,8 +11,8 @@ **********************************************************************/ #include "ruby.h" -#include "env.h" #include "st.h" +#include "yarv.h" #include <stdio.h> #include <stdarg.h> @@ -24,21 +24,23 @@ #endif extern const char ruby_version[], ruby_release_date[], ruby_platform[]; - int ruby_nerrs; +const char *rb_sourcefile(); +int rb_sourceline(); + static int err_position(char *buf, long len) { ruby_set_current_source(); - if (!ruby_sourcefile) { + if (!rb_sourcefile()) { return 0; } - else if (ruby_sourceline == 0) { - return snprintf(buf, len, "%s: ", ruby_sourcefile); + else if (rb_sourceline() == 0) { + return snprintf(buf, len, "%s: ", rb_sourcefile()); } else { - return snprintf(buf, len, "%s:%d: ", ruby_sourcefile, ruby_sourceline); + return snprintf(buf, len, "%s:%d: ", rb_sourcefile(), rb_sourceline()); } } @@ -67,7 +69,6 @@ void rb_compile_error(const char *fmt, ...) { va_list args; - va_start(args, fmt); err_print(fmt, args); va_end(args); @@ -147,6 +148,8 @@ rb_warn_m(VALUE self, VALUE mesg) return Qnil; } +void yarv_bug(); + void rb_bug(const char *fmt, ...) { @@ -157,6 +160,7 @@ rb_bug(const char *fmt, ...) if (fwrite(buf, 1, len, out) == len || fwrite(buf, 1, len, (out = stdout)) == len) { + yarv_bug(); fputs("[BUG] ", out); va_start(args, fmt); vfprintf(out, fmt, args); @@ -164,6 +168,7 @@ rb_bug(const char *fmt, ...) fprintf(out, "\nruby %s (%s) [%s]\n\n", ruby_version, ruby_release_date, ruby_platform); } + abort(); } @@ -190,8 +195,6 @@ static struct types { {T_SYMBOL, "Symbol"}, /* :symbol */ {T_DATA, "Data"}, /* internal use: wrapped C pointers */ {T_MATCH, "MatchData"}, /* data of $~ */ - {T_VARMAP, "Varmap"}, /* internal use: dynamic variables */ - {T_SCOPE, "Scope"}, /* internal use: variable scope */ {T_NODE, "Node"}, /* internal use: syntax tree node */ {T_UNDEF, "undef"}, /* internal use: #undef; should not happen */ {-1, 0} @@ -1024,9 +1027,9 @@ rb_loaderror(const char *fmt, ...) void rb_notimplement(void) { - rb_raise(rb_eNotImpError, - "The %s() function is unimplemented on this machine", - rb_id2name(ruby_frame->callee)); + rb_raise(rb_eNotImpError, + "The %s() function is unimplemented on this machine", + rb_id2name(rb_frame_callee())); } void @@ -1039,7 +1042,6 @@ rb_fatal(const char *fmt, ...) vsnprintf(buf, BUFSIZ, fmt, args); va_end(args); - ruby_in_eval = 0; rb_exc_fatal(rb_exc_new2(rb_eFatal, buf)); } @@ -1471,22 +1473,21 @@ Init_syserr(void) static void err_append(const char *s) { - extern VALUE ruby_errinfo; - - if (ruby_in_eval) { - if (NIL_P(ruby_errinfo)) { - ruby_errinfo = rb_exc_new2(rb_eSyntaxError, s); - } - else { - VALUE str = rb_obj_as_string(ruby_errinfo); - - rb_str_cat2(str, "\n"); - rb_str_cat2(str, s); - ruby_errinfo = rb_exc_new3(rb_eSyntaxError, str); - } + yarv_thread_t *th = GET_THREAD(); + if (th->parse_in_eval) { + if (NIL_P(th->errinfo)) { + th->errinfo = rb_exc_new2(rb_eSyntaxError, s); } else { - rb_write_error(s); - rb_write_error("\n"); + VALUE str = rb_obj_as_string(GET_THREAD()->errinfo); + + rb_str_cat2(str, "\n"); + rb_str_cat2(str, s); + th->errinfo = rb_exc_new3(rb_eSyntaxError, str); } + } + else { + rb_write_error(s); + rb_write_error("\n"); + } } @@ -12,1067 +12,40 @@ **********************************************************************/ -#include "ruby.h" -#include "node.h" -#include "env.h" -#include "util.h" -#include "rubysig.h" - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifndef EXIT_SUCCESS -#define EXIT_SUCCESS 0 -#endif -#ifndef EXIT_FAILURE -#define EXIT_FAILURE 1 -#endif - -#include <stdio.h> - -#include "st.h" -#include "dln.h" - -#ifdef __APPLE__ -#include <crt_externs.h> -#endif - -/* Make alloca work the best possible way. */ -#ifdef __GNUC__ -# ifndef atarist -# ifndef alloca -# define alloca __builtin_alloca -# endif -# endif /* atarist */ -#else -# ifdef HAVE_ALLOCA_H -# include <alloca.h> -# else -# ifndef _AIX -# ifndef alloca /* predefined by HP cc +Olibcalls */ -void *alloca (); -# endif -# endif /* AIX */ -# endif /* HAVE_ALLOCA_H */ -#endif /* __GNUC__ */ - -#include <stdarg.h> - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef __BEOS__ -#include <net/socket.h> -#endif - -#ifdef __MACOS__ -#include "macruby_private.h" -#endif - -#ifdef __VMS -#include "vmsruby_private.h" -#endif - -#ifdef USE_CONTEXT - -NORETURN(static void rb_jump_context(rb_jmpbuf_t, int)); -static inline void -rb_jump_context(rb_jmpbuf_t env, int val) -{ - env->status = val; - setcontext(&env->context); - abort(); /* ensure noreturn */ -} -/* - * PRE_GETCONTEXT and POST_GETCONTEXT is a magic for getcontext, gcc, - * IA64 register stack and SPARC register window combination problem. - * - * Assume following code sequence. - * - * 1. set a register in the register stack/window such as r32/l0. - * 2. call getcontext. - * 3. use the register. - * 4. update the register for other use. - * 5. call setcontext indirectly (or directly). - * - * This code should be run as 1->2->3->4->5->3->4. - * But after second getcontext return (second 3), - * the register is broken (updated). - * It's because getcontext/setcontext doesn't preserve the content of the - * register stack/window. - * - * setjmp also doesn't preserve the content of the register stack/window. - * But it has not the problem because gcc knows setjmp may return twice. - * gcc detects setjmp and generates setjmp safe code. - * - * So setjmp calls before and after getcontext call makes the code - * somewhat safe. - * It fix the problem on IA64. - * It is not required that setjmp is called at run time, since the problem is - * register usage. - * - * Since the magic setjmp is not enough for SPARC, - * inline asm is used to prohibit registers in register windows. - * - * Since the problem is fixed at gcc 4.0.3, the magic is applied only for - * prior versions of gcc. - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21957 - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22127 - */ -# define GCC_VERSION_BEFORE(major, minor, patchlevel) \ - (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \ - ((__GNUC__ < (major)) || \ - (__GNUC__ == (major) && __GNUC_MINOR__ < (minor)) || \ - (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ < (patchlevel)))) -# if GCC_VERSION_BEFORE(4,0,3) && (defined(sparc) || defined(__sparc__)) -# ifdef __pic__ -/* - * %l7 is excluded for PIC because it is PIC register. - * http://lists.freebsd.org/pipermail/freebsd-sparc64/2006-January/003739.html - */ -# define PRE_GETCONTEXT \ - ({ __asm__ volatile ("" : : : \ - "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", \ - "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", \ - "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); }), -# else -# define PRE_GETCONTEXT \ - ({ __asm__ volatile ("" : : : \ - "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", \ - "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \ - "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); }), -# endif -# define POST_GETCONTEXT PRE_GETCONTEXT -# elif GCC_VERSION_BEFORE(4,0,3) && defined(__ia64) -static jmp_buf function_call_may_return_twice_jmp_buf; -int function_call_may_return_twice_false_1 = 0; -int function_call_may_return_twice_false_2 = 0; -# define PRE_GETCONTEXT \ - (function_call_may_return_twice_false_1 ? \ - setjmp(function_call_may_return_twice_jmp_buf) : \ - 0), -# define POST_GETCONTEXT \ - (function_call_may_return_twice_false_2 ? \ - setjmp(function_call_may_return_twice_jmp_buf) : \ - 0), -# elif defined(__FreeBSD__) && __FreeBSD__ < 7 -/* - * workaround for FreeBSD/i386 getcontext/setcontext bug. - * clear the carry flag by (0 ? ... : ...). - * FreeBSD PR 92110 http://www.freebsd.org/cgi/query-pr.cgi?pr=92110 - * [ruby-dev:28263] - */ -static int volatile freebsd_clear_carry_flag = 0; -# define PRE_GETCONTEXT \ - (freebsd_clear_carry_flag ? (freebsd_clear_carry_flag = 0) : 0), -# endif -# ifndef PRE_GETCONTEXT -# define PRE_GETCONTEXT -# endif -# ifndef POST_GETCONTEXT -# define POST_GETCONTEXT -# endif -# define ruby_longjmp(env, val) rb_jump_context(env, val) -# define ruby_setjmp(just_before_setjmp, j) ((j)->status = 0, \ - (just_before_setjmp), \ - PRE_GETCONTEXT \ - getcontext(&(j)->context), \ - POST_GETCONTEXT \ - (j)->status) -#else -# if !defined(setjmp) && defined(HAVE__SETJMP) -# define ruby_setjmp(just_before_setjmp, env) \ - ((just_before_setjmp), _setjmp(env)) -# define ruby_longjmp(env,val) _longjmp(env,val) -# else -# define ruby_setjmp(just_before_setjmp, env) \ - ((just_before_setjmp), setjmp(env)) -# define ruby_longjmp(env,val) longjmp(env,val) -# endif -#endif - -#include <sys/types.h> -#include <signal.h> -#include <errno.h> - -#if defined(__VMS) -#pragma nostandard -#endif - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -/* - Solaris sys/select.h switches select to select_large_fdset to support larger - file descriptors if FD_SETSIZE is larger than 1024 on 32bit environment. - But Ruby doesn't change FD_SETSIZE because fd_set is allocated dynamically. - So following definition is required to use select_large_fdset. -*/ -#ifdef HAVE_SELECT_LARGE_FDSET -#define select(n, r, w, e, t) select_large_fdset(n, r, w, e, t) -#endif - -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif - -#include <sys/stat.h> +#include "eval_intern.h" VALUE rb_cProc; VALUE rb_cBinding; -static VALUE proc_alloc(VALUE,struct BLOCK*,int); -static VALUE proc_invoke(VALUE,VALUE,VALUE,VALUE,int); -#define INVOKE_CALL (YIELD_CALL|YIELD_VALUES) -#define INVOKE_VALUES YIELD_VALUES - -static VALUE proc_lambda(void); -static VALUE rb_f_binding(VALUE); -static void rb_f_END(void); -static struct BLOCK *passing_block(VALUE,struct BLOCK*); -static int block_orphan(struct BLOCK *data); - -VALUE rb_cMethod; -VALUE rb_cUnboundMethod; -static VALUE umethod_bind(VALUE, VALUE); -static VALUE rb_mod_define_method(int, VALUE*, VALUE); -static VALUE rb_obj_define_method(int, VALUE*, VALUE); -NORETURN(static void rb_raise_jump(VALUE)); -static VALUE rb_make_exception(int argc, VALUE *argv); - -static int vis_mode; -#define VIS_PUBLIC 0 -#define VIS_PRIVATE 1 -#define VIS_PROTECTED 2 -#define VIS_MODFUNC 5 -#define VIS_LOCAL 8 -#define VIS_MASK 15 -#define VIS_SET(f) (vis_mode=(f)) -#define VIS_TEST(f) (vis_mode&(f)) -#define VIS_MODE() (vis_mode) - -VALUE (*ruby_sandbox_save)(struct thread *) = NULL; -VALUE (*ruby_sandbox_restore)(struct thread *) = NULL; -NODE* ruby_current_node; -int ruby_safe_level = 0; -/* safe-level: - 0 - strings from streams/environment/ARGV are tainted (default) - 1 - no dangerous operation by tainted value - 2 - process/file operations prohibited - 3 - all generated objects are tainted - 4 - no global (non-tainted) variable modification/no direct output -*/ - -static VALUE safe_getter(void); -static void safe_setter(VALUE val); -void -rb_secure(int level) -{ - if (level <= ruby_safe_level) { - if (ruby_frame->callee) { - rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d", - rb_id2name(ruby_frame->callee), ruby_safe_level); - } - else { - rb_raise(rb_eSecurityError, "Insecure operation at level %d", ruby_safe_level); - } - } -} - -void -rb_secure_update(VALUE obj) -{ - if (!OBJ_TAINTED(obj)) rb_secure(4); -} +VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE); +VALUE rb_f_binding(VALUE); -void -rb_check_safe_obj(VALUE x) -{ - if (ruby_safe_level > 0 && OBJ_TAINTED(x)){ - if (ruby_frame->callee) { - rb_raise(rb_eSecurityError, "Insecure operation - %s", - rb_id2name(ruby_frame->callee)); - } - else { - rb_raise(rb_eSecurityError, "Insecure operation: -r"); - } - } - rb_secure(4); -} +VALUE rb_f_block_given_p(void); -void -rb_check_safe_str(VALUE x) -{ - rb_check_safe_obj(x); - if (TYPE(x)!= T_STRING) { - rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", - rb_obj_classname(x)); - } -} +ID rb_frame_callee(void); +static VALUE rb_frame_self(void); -NORETURN(static void raise_undef(VALUE, ID)); -static void -raise_undef(VALUE klass, ID id) -{ - rb_name_error(id, "undefined method `%s' for %s `%s'", - rb_id2name(id), - (TYPE(klass) == T_MODULE) ? "module" : "class", - rb_class2name(klass)); -} +NODE *ruby_current_node; static ID removed, singleton_removed, undefined, singleton_undefined; - -#define CACHE_SIZE 0x800 -#define CACHE_MASK 0x7ff -#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK) - -struct cache_entry { /* method hash table. */ - ID mid; /* method's id */ - ID mid0; /* method's original id */ - VALUE klass; /* receiver's class */ - VALUE origin; /* where method defined */ - NODE *method; - int noex; -}; - -static struct cache_entry cache[2][CACHE_SIZE]; -static int ruby_running = 0; - -void -rb_clear_cache() -{ - int i; - - if (!ruby_running) return; - for (i=0; i<CACHE_SIZE; i++) { - cache[0][i].mid = cache[1][i].mid = 0; - } -} - -static void -rb_clear_cache_for_remove(VALUE klass, ID id) -{ - int i, j; - - if (!ruby_running) return; - for (i=0; i<CACHE_SIZE; i++) { - for (j=0; j<2; j++) { - struct cache_entry *ent = cache[j]+i; - if (ent->mid == id && - RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl) { - ent->mid = 0; - } - } - } -} - -static void -rb_clear_cache_by_id(ID id) -{ - int i, j; - - if (!ruby_running) return; - for (i=0; i<CACHE_SIZE; i++) { - for (j=0; j<2; j++) { - struct cache_entry *ent = cache[j]+i; - if (ent->mid == id) { - ent->mid = 0; - } - } - } -} - -void -rb_clear_cache_by_class(VALUE klass) -{ - int i, j; - - if (!ruby_running) return; - for (i=0; i<CACHE_SIZE; i++) { - for (j=0; j<2; j++) { - struct cache_entry *ent = cache[j]+i; - if (ent->klass == klass || ent->origin == klass) { - ent->mid = 0; - } - } - } -} - static ID init, eqq, each, aref, aset, match, missing; static ID added, singleton_added; static ID object_id, __send, __send_bang, respond_to; -#define NOEX_SAFE(n) ((n) >> 5) -#define NOEX_WITH(n, v) ((n) | (v) << 5) -#define NOEX_WITH_SAFE(n) NOEX_WITH(n, ruby_safe_level) - -void -rb_add_method(VALUE klass, ID mid, NODE *node, int noex) -{ - NODE *body; - - if (NIL_P(klass)) klass = rb_cObject; - if (ruby_safe_level >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) { - rb_raise(rb_eSecurityError, "Insecure: can't define method"); - } - if (!FL_TEST(klass, FL_SINGLETON) && - node && nd_type(node) != NODE_ZSUPER && - (mid == rb_intern("initialize" )|| mid == rb_intern("initialize_copy"))) { - noex = NOEX_PRIVATE | noex; - } - else if (FL_TEST(klass, FL_SINGLETON) && node && nd_type(node) == NODE_CFUNC && - mid == rb_intern("allocate")) { - rb_warn("defining %s.allocate is deprecated; use rb_define_alloc_func()", - rb_class2name(rb_iv_get(klass, "__attached__"))); - mid = ID_ALLOCATOR; - } - if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); - rb_clear_cache_by_id(mid); - body = NEW_METHOD(node, NOEX_WITH_SAFE(noex)); - st_insert(RCLASS(klass)->m_tbl, mid, (st_data_t)body); - if (node && mid != ID_ALLOCATOR && ruby_running) { - if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1, ID2SYM(mid)); - } - else { - rb_funcall(klass, added, 1, ID2SYM(mid)); - } - } -} - -void -rb_define_alloc_func(VALUE klass, VALUE (*func) (VALUE)) -{ - Check_Type(klass, T_CLASS); - rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE); -} - -void -rb_undef_alloc_func(VALUE klass) -{ - Check_Type(klass, T_CLASS); - rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF); -} - -#define LOOKUP_NORMAL 0 -#define LOOKUP_FCALL 1 -#define LOOKUP_NOSKIP 2 -#define LOOKUP_LOCAL 1 - -static NODE* -search_method(VALUE klass, ID id, VALUE *origin, int flag, int *out) -{ - NODE *body; - - if (flag == LOOKUP_FCALL && ruby_frame->this_class) { - if (st_lookup(RCLASS(ruby_frame->this_class)->m_tbl, id, (st_data_t *)&body) && - body->nd_noex == NOEX_LOCAL) { - if (origin) *origin = ruby_frame->this_class; - if (out) *out = LOOKUP_LOCAL; - return body; - } - } - for (;klass; klass = RCLASS(klass)->super) { - if (st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *)&body) && - (flag == LOOKUP_NOSKIP || body->nd_noex != NOEX_LOCAL)) { - if (origin) *origin = klass; - if (out) *out = LOOKUP_NORMAL; - return body; - } - } - return 0; -} - -static NODE* -rb_get_method_body(VALUE *klassp, ID *idp, int *noexp) -{ - ID id = *idp; - VALUE klass = *klassp; - VALUE origin; - NODE * volatile body; - struct cache_entry *ent; - int noex = *noexp; - int lc; - - if ((body = search_method(klass, id, &origin, noex, &lc)) == 0 || !body->nd_body) { - /* store empty info in cache */ - ent = cache[noex] + EXPR1(klass, id); - ent->klass = klass; - ent->origin = klass; - ent->mid = ent->mid0 = id; - ent->noex = 0; - ent->method = 0; - - return 0; - } - - if (ruby_running) { - VALUE c = (lc == LOOKUP_LOCAL) ? origin : klass; - /* store in cache */ - ent = cache[lc] + EXPR1(c, id); - ent->klass = c; - ent->noex = body->nd_noex; - if (noexp) *noexp = body->nd_noex; - body = body->nd_body; - if (nd_type(body) == NODE_FBODY) { - ent->mid = id; - *klassp = body->nd_orig; - ent->origin = body->nd_orig; - *idp = ent->mid0 = body->nd_mid; - body = ent->method = body->nd_head; - } - else { - *klassp = origin; - ent->origin = origin; - ent->mid = ent->mid0 = id; - ent->method = body; - } - } - else { - if (noexp) *noexp = body->nd_noex; - body = body->nd_body; - if (nd_type(body) == NODE_FBODY) { - *klassp = body->nd_orig; - *idp = body->nd_mid; - body = body->nd_head; - } - else { - *klassp = origin; - } - } - - return body; -} - -NODE* -rb_method_node(VALUE klass, ID id) -{ - int noex = LOOKUP_NORMAL; - struct cache_entry *ent; - - ent = cache[0] + EXPR1(klass, id); - if (ent->mid == id && ent->klass == klass && ent->method){ - return ent->method; - } - - return rb_get_method_body(&klass, &id, &noex); -} - -static void -remove_method(VALUE klass, ID mid) -{ - NODE *body; - - if (klass == rb_cObject) { - rb_secure(4); - } - if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) { - rb_raise(rb_eSecurityError, "Insecure: can't remove method"); - } - if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); - if (mid == object_id || mid == __send || mid == __send_bang || mid == init) { - rb_warn("removing `%s' may cause serious problem", rb_id2name(mid)); - } - if (!st_delete(RCLASS(klass)->m_tbl, &mid, (st_data_t *)&body) || - !body->nd_body) { - rb_name_error(mid, "method `%s' not defined in %s", - rb_id2name(mid), rb_class2name(klass)); - } - rb_clear_cache_for_remove(klass, mid); - if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1, ID2SYM(mid)); - } - else { - rb_funcall(klass, removed, 1, ID2SYM(mid)); - } -} - -void -rb_remove_method(VALUE klass, const char *name) -{ - remove_method(klass, rb_intern(name)); -} - -/* - * call-seq: - * remove_method(symbol) => self - * - * Removes the method identified by _symbol_ from the current - * class. For an example, see <code>Module.undef_method</code>. - */ - -static VALUE -rb_mod_remove_method(int argc, VALUE *argv, VALUE mod) -{ - int i; - - for (i=0; i<argc; i++) { - remove_method(mod, rb_to_id(argv[i])); - } - return mod; -} - -#undef rb_disable_super -#undef rb_enable_super - -void -rb_disable_super(VALUE klass, const char *name) -{ - /* obsolete - no use */ -} - -void -rb_enable_super(VALUE klass, const char *name) -{ - rb_warning("rb_enable_super() is obsolete"); -} - -static void -rb_export_method(VALUE klass, ID name, ID noex) -{ - NODE *body; - VALUE origin; - - if (klass == rb_cObject) { - rb_secure(4); - } - body = search_method(klass, name, &origin, LOOKUP_NOSKIP, 0); - if (!body && TYPE(klass) == T_MODULE) { - body = search_method(rb_cObject, name, &origin, LOOKUP_NOSKIP, 0); - } - if (!body || !body->nd_body) { - raise_undef(klass, name); - } - if (body->nd_noex != noex) { - if (klass == origin) { - body->nd_noex = noex; - } - else { - rb_add_method(klass, name, NEW_ZSUPER(), noex); - } - } -} - -static int -method_exists(VALUE klass, ID id, int noex) -{ - struct cache_entry *ent; - int nx = noex; - - switch (noex) { - case LOOKUP_NORMAL: - case LOOKUP_FCALL: - /* is it in the method cache? */ - ent = cache[noex] + EXPR1(klass, id); - if (ent->mid == id && ent->klass == klass) { - if (nx == LOOKUP_NORMAL) { - if (ent->noex == NOEX_PRIVATE) return Qfalse; - } - else if (ent->noex != NOEX_LOCAL) { - if (!ent->method) return Qfalse; - return Qtrue; - } - } - /* fall through */ - default: - if (rb_get_method_body(&klass, &id, &noex)) { - if (nx == LOOKUP_NORMAL && noex == NOEX_PRIVATE) - return Qfalse; - return Qtrue; - } - return Qfalse; - } -} - -int -rb_method_boundp(VALUE klass, ID id, int pub) -{ - return method_exists(klass, id, pub ? LOOKUP_NORMAL : LOOKUP_FCALL); -} - -void -rb_attr(VALUE klass, ID id, int read, int write, int noex) -{ - const char *name; - char *buf; - ID attriv; - size_t len; - - if (!noex) noex = NOEX_PUBLIC; - else { - if (VIS_TEST(VIS_PRIVATE)) { - noex = NOEX_PRIVATE; - rb_warning((VIS_MODE() == VIS_MODFUNC) ? - "attribute accessor as module_function" : - "private attribute?"); - } - else if (VIS_TEST(VIS_PROTECTED)) { - noex = NOEX_PROTECTED; - } - else { - noex = NOEX_PUBLIC; - } - } - - if (!rb_is_local_id(id) && !rb_is_const_id(id)) { - rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); - } - name = rb_id2name(id); - if (!name) { - rb_raise(rb_eArgError, "argument needs to be symbol or string"); - } - len = strlen(name)+2; - buf = ALLOCA_N(char,len); - snprintf(buf, len, "@%s", name); - attriv = rb_intern(buf); - if (read) { - rb_add_method(klass, id, NEW_IVAR(attriv), noex); - } - if (write) { - rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex); - } -} - -VALUE ruby_errinfo = Qnil; -extern int ruby_nerrs; - VALUE rb_eLocalJumpError; VALUE rb_eSysStackError; +extern int ruby_nerrs; extern VALUE ruby_top_self; -struct FRAME *ruby_frame; -struct SCOPE *ruby_scope; -static struct FRAME *top_frame; -static struct SCOPE *top_scope; - -static unsigned long frame_unique = 1; - -#define PUSH_FRAME(link) do { \ - struct FRAME _frame; \ - _frame.prev = ruby_frame; \ - _frame.tmp = 0; \ - _frame.node = ruby_current_node; \ - _frame.argc = 0; \ - _frame.self = (link)?ruby_frame->self:0;\ - _frame.block = (link)?ruby_frame->block:0;\ - _frame.flags = 0; \ - _frame.uniq = frame_unique++; \ - _frame.callee = 0; \ - _frame.this_func = 0; \ - _frame.this_class = 0; \ - ruby_frame = &_frame - -#define POP_FRAME() \ - ruby_current_node = _frame.node; \ - ruby_frame = _frame.prev; \ -} while (0) - -static unsigned long block_unique = 1; - -#define PUSH_BLOCK(v,iv,b) do { \ - struct BLOCK _block; \ - _block.var = (iv); \ - _block.body = (b); \ - _block.self = self; \ - _block.frame = *ruby_frame; \ - _block.cref = ruby_cref; \ - _block.frame.node = ruby_current_node;\ - _block.scope = ruby_scope; \ - _block.vmode = vis_mode; \ - _block.flags = BLOCK_D_SCOPE; \ - _block.dyna_vars = ruby_dyna_vars; \ - _block.wrapper = ruby_wrapper; \ - _block.block_obj = 0; \ - if (b) { \ - _block.uniq = block_unique++; \ - prot_tag->blkid = _block.uniq; \ - } \ - else { \ - _block.uniq = 0; \ - prot_tag->blkid = 0; \ - } \ - (v) = &_block - -#define POP_BLOCK() } while (0) - -struct RVarmap *ruby_dyna_vars; -#define PUSH_VARS() do { \ - struct RVarmap * volatile _old; \ - _old = ruby_dyna_vars; \ - ruby_dyna_vars = 0 - -#define POP_VARS() \ - if (_old && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) {\ - if (RBASIC(_old)->flags) /* unless it's already recycled */ \ - FL_SET(_old, DVAR_DONT_RECYCLE); \ - }\ - ruby_dyna_vars = _old; \ -} while (0) - -#define DVAR_DONT_RECYCLE FL_USER2 - -#define DMETHOD_P() (ruby_frame->flags & FRAME_DMETH) - -static struct RVarmap* -new_dvar(ID id, VALUE value, struct RVarmap *prev) -{ - NEWOBJ(vars, struct RVarmap); - OBJSETUP(vars, 0, T_VARMAP); - vars->id = id; - vars->val = value; - vars->next = prev; +static VALUE ruby_wrapper; /* security wrapper */ - return vars; -} +static VALUE eval _((VALUE, VALUE, VALUE, char *, int)); -VALUE -rb_dvar_defined(ID id) -{ - struct RVarmap *vars = ruby_dyna_vars; - - while (vars) { - if (vars->id == id) return Qtrue; - vars = vars->next; - } - return Qfalse; -} - -VALUE -rb_dvar_curr(ID id) -{ - struct RVarmap *vars = ruby_dyna_vars; +static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int)); +static VALUE rb_call(VALUE, VALUE, ID, int, const VALUE *, int); - while (vars) { - if (vars->id == 0) break; - if (vars->id == id) return Qtrue; - vars = vars->next; - } - return Qfalse; -} - -VALUE -rb_dvar_ref(ID id) -{ - struct RVarmap *vars = ruby_dyna_vars; - - while (vars) { - if (vars->id == id) { - return vars->val; - } - vars = vars->next; - } - return Qnil; -} - -void -rb_dvar_push(ID id, VALUE value) -{ - ruby_dyna_vars = new_dvar(id, value, ruby_dyna_vars); -} - -static void -dvar_asgn_internal(ID id, VALUE value, int curr) -{ - int n = 0; - struct RVarmap *vars = ruby_dyna_vars; - - while (vars) { - if (curr && vars->id == 0) { - /* first null is a dvar header */ - n++; - if (n == 2) break; - } - if (vars->id == id) { - vars->val = value; - return; - } - vars = vars->next; - } - if (!ruby_dyna_vars) { - ruby_dyna_vars = new_dvar(id, value, 0); - } - else { - vars = new_dvar(id, value, ruby_dyna_vars->next); - ruby_dyna_vars->next = vars; - } -} - -static inline void -dvar_asgn(ID id, VALUE value) -{ - dvar_asgn_internal(id, value, 0); -} - -static inline void -dvar_asgn_curr(ID id, VALUE value) -{ - dvar_asgn_internal(id, value, 1); -} - -VALUE * -rb_svar(int cnt) -{ - struct RVarmap *vars = ruby_dyna_vars; - ID id; - - if (!ruby_scope->local_tbl) return NULL; - if (cnt >= ruby_scope->local_tbl[0]) return NULL; - id = ruby_scope->local_tbl[cnt+1]; - while (vars) { - if (vars->id == id) return &vars->val; - vars = vars->next; - } - if (ruby_scope->local_vars == 0) return NULL; - return &ruby_scope->local_vars[cnt]; -} - -struct tag { - rb_jmpbuf_t buf; - struct FRAME *frame; - VALUE tag; - VALUE retval; - struct SCOPE *scope; - VALUE dst; - struct tag *prev; - int blkid; -}; -static struct tag *prot_tag; - -#define PUSH_TAG(ptag) do { \ - struct tag _tag; \ - _tag.retval = Qnil; \ - _tag.frame = ruby_frame; \ - _tag.prev = prot_tag; \ - _tag.scope = ruby_scope; \ - _tag.tag = ptag; \ - _tag.dst = -1; \ - _tag.blkid = 0; \ - prot_tag = &_tag - -#define PROT_NONE Qfalse /* 0 */ -#define PROT_THREAD Qtrue /* 2 */ -#define PROT_FUNC INT2FIX(0) /* 1 */ -#define PROT_LOOP INT2FIX(1) /* 3 */ -#define PROT_LAMBDA INT2FIX(2) /* 5 */ -#define PROT_YIELD INT2FIX(3) /* 7 */ -#define PROT_TOP INT2FIX(4) /* 9 */ - -#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, ruby_setjmp(((void)0), prot_tag->buf)) - -#define JUMP_TAG(st) do { \ - ruby_frame = prot_tag->frame; \ - ruby_longjmp(prot_tag->buf,(st)); \ -} while (0) - -#define POP_TAG() \ - prot_tag = _tag.prev; \ -} while (0) - -#define TAG_DST() (_tag.dst == (VALUE)ruby_frame->uniq) - -#define TAG_RETURN 0x1 -#define TAG_BREAK 0x2 -#define TAG_NEXT 0x3 -#define TAG_RETRY 0x4 -#define TAG_REDO 0x5 -#define TAG_RAISE 0x6 -#define TAG_THROW 0x7 -#define TAG_FATAL 0x8 -#define TAG_CONTCALL 0x9 -#define TAG_THREAD 0xa -#define TAG_MASK 0xf - -VALUE ruby_wrapper; /* security wrapper */ - -NODE *ruby_cref = 0; -NODE *ruby_top_cref; -#define PUSH_CREF(c) ruby_cref = NEW_NODE(NODE_CREF,(c),0,ruby_cref) -#define POP_CREF() ruby_cref = ruby_cref->nd_next - -#define PUSH_SCOPE() do { \ - volatile int _vmode = vis_mode; \ - struct SCOPE * volatile _old; \ - NEWOBJ(_scope, struct SCOPE); \ - OBJSETUP(_scope, 0, T_SCOPE); \ - _scope->local_tbl = 0; \ - _scope->local_vars = 0; \ - _scope->flags = 0; \ - _old = ruby_scope; \ - ruby_scope = _scope; \ - vis_mode = VIS_PUBLIC - -rb_thread_t curr_thread = 0; -rb_thread_t main_thread; -static void scope_dup(struct SCOPE *); - -#define POP_SCOPE() \ - if (ruby_scope->flags & SCOPE_DONT_RECYCLE) {\ - if (_old) scope_dup(_old); \ - } \ - if (!(ruby_scope->flags & SCOPE_MALLOC)) {\ - ruby_scope->local_vars = 0; \ - ruby_scope->local_tbl = 0; \ - if (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) && \ - ruby_scope != top_scope) { \ - rb_gc_force_recycle((VALUE)ruby_scope);\ - } \ - } \ - ruby_scope->flags |= SCOPE_NOSTACK; \ - ruby_scope = _old; \ - vis_mode = _vmode; \ -} while (0) - -struct ruby_env { - struct ruby_env *prev; - struct FRAME *frame; - struct SCOPE *scope; - struct BLOCK *block; - struct tag *tag; - NODE *cref; -}; - -static void push_thread_anchor(struct ruby_env *); -static void pop_thread_anchor(struct ruby_env *); - -#define PUSH_THREAD_TAG() PUSH_TAG(PROT_THREAD); \ - do { \ - struct ruby_env _interp; \ - push_thread_anchor(&_interp); -#define POP_THREAD_TAG() \ - pop_thread_anchor(&_interp); \ - } while (0); \ - POP_TAG() - -static VALUE rb_eval(VALUE,NODE*); -static VALUE eval(VALUE,VALUE,VALUE,const char*,int); -static NODE *compile(VALUE, const char*, int); - -static VALUE rb_yield_0(VALUE, VALUE, VALUE, int); - -#define YIELD_CALL 1 -#define YIELD_VALUES 2 -#define YIELD_PROC_INVOKE 4 -#define YIELD_PUBLIC_DEF 8 -#define YIELD_FUNC_AVALUE 1 -#define YIELD_FUNC_SVALUE 2 - -typedef enum calling_scope { - CALLING_NORMAL, - CALLING_FUNCALL, - CALLING_FCALL, - CALLING_VCALL, - CALLING_SUPER, -} calling_scope_t; - -static VALUE rb_call(VALUE,VALUE,ID,int,const VALUE*,struct BLOCK*,calling_scope_t,int,VALUE); -static VALUE module_setup(VALUE,NODE*); - -static VALUE massign(VALUE,NODE*,VALUE,int); -static void assign(VALUE,NODE*,VALUE,int); -static int formal_assign(VALUE, NODE*, int, const VALUE*, VALUE*); +static void rb_clear_trace_func(void); typedef struct event_hook { rb_event_hook_func_t func; @@ -1084,235 +57,24 @@ static rb_event_hook_t *event_hooks; #define EXEC_EVENT_HOOK(event, node, self, id, klass) \ do { \ - rb_event_hook_t *hook = event_hooks; \ - rb_event_hook_func_t hook_func; \ - rb_event_t events; \ + rb_event_hook_t *hook; \ \ - while (hook) { \ - hook_func = hook->func; \ - events = hook->events; \ - hook = hook->next; \ - if (events & event) \ - (*hook_func)(event, node, self, id, klass); \ + for (hook = event_hooks; hook; hook = hook->next) { \ + if (hook->events & event) \ + (*hook->func)(event, node, self, id, klass); \ } \ } while (0) -static VALUE trace_func = 0; -static int tracing = 0; -static void call_trace_func(rb_event_t,NODE*,VALUE,ID,VALUE); - -#if 0 -#define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \ - ruby_sourceline = nd_line(ruby_current_node)) -#else -#define SET_CURRENT_SOURCE() ((void)0) -#endif - -void -ruby_set_current_source(void) -{ - if (ruby_current_node) { - ruby_sourcefile = ruby_current_node->nd_file; - ruby_sourceline = nd_line(ruby_current_node); - } -} - -static void -warn_printf(const char *fmt, ...) -{ - char buf[BUFSIZ]; - va_list args; - - va_start(args, fmt); - vsnprintf(buf, BUFSIZ, fmt, args); - va_end(args); - rb_write_error(buf); -} - -static VALUE -error_line(struct FRAME *frame, NODE *node) -{ - char *file; - int line; - - if (node) { - file = node->nd_file; - line = nd_line(node); - } - else { - file = ruby_sourcefile; - line = ruby_sourceline; - } - ruby_set_current_source(); - if (ruby_sourcefile) { - if (frame->callee) { - if (frame->flags & FRAME_FUNC) { - return rb_sprintf("%s:%d:in `%s'", file, line, - rb_id2name(frame->this_func)); - } - else { - VALUE oklass = frame->this_class; - char *rec = 0; - - switch (TYPE(frame->self)) { - case T_NIL: - rec = "nil"; break; - case T_TRUE: - rec = "true"; break; - case T_FALSE: - rec = "false"; break; - } - if (rec) { - return rb_sprintf("%s:%d:in `%s.%s'", file, line, rec, - rb_id2name(frame->this_func)); - } - if (TYPE(oklass) == T_ICLASS) { - oklass = RBASIC(oklass)->klass; - } - else if (FL_TEST(oklass, FL_SINGLETON)) { - oklass = rb_iv_get(oklass, "__attached__"); - } - return rb_sprintf("%s:%d:in `%s#%s'", file, line, - rb_class2name(oklass), - rb_id2name(frame->this_func)); - } - } - else if (!node && ruby_sourceline == 0) { - return rb_str_new2(ruby_sourcefile); - } - } - return rb_sprintf("%s:%d", file, line); -} - -#define warn_print(x) rb_write_error(x) -#define warn_print2(x,l) rb_write_error2(x,l) - -static void -error_pos(void) -{ - VALUE pos = error_line(ruby_frame, 0); - warn_printf("%s", StringValueCStr(pos)); -} - -static VALUE -get_backtrace(VALUE info) -{ - if (NIL_P(info)) return Qnil; - info = rb_funcall(info, rb_intern("backtrace"), 0); - if (NIL_P(info)) return Qnil; - return rb_check_array_type(info); -} - -static void -set_backtrace(VALUE info, VALUE bt) -{ - rb_funcall(info, rb_intern("set_backtrace"), 1, bt); -} - -static void -error_print(void) -{ - VALUE errat = Qnil; /* OK */ - volatile VALUE eclass, e; - const char *einfo; - long elen; - - if (NIL_P(ruby_errinfo)) return; - - PUSH_TAG(PROT_NONE); - if (EXEC_TAG() == 0) { - errat = get_backtrace(ruby_errinfo); - } - else { - errat = Qnil; - } - if (EXEC_TAG()) goto error; - if (NIL_P(errat)){ - ruby_set_current_source(); - if (ruby_sourcefile) - warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline); - else - warn_printf("%d", ruby_sourceline); - } - else if (RARRAY_LEN(errat) == 0) { - error_pos(); - } - else { - VALUE mesg = RARRAY_PTR(errat)[0]; - - if (NIL_P(mesg)) error_pos(); - else { - warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg)); - } - } +static void call_trace_func _((rb_event_t, NODE *, VALUE, ID, VALUE)); - eclass = CLASS_OF(ruby_errinfo); - if (EXEC_TAG() == 0) { - e = rb_funcall(ruby_errinfo, rb_intern("message"), 0, 0); - StringValue(e); - einfo = RSTRING_PTR(e); - elen = RSTRING_LEN(e); - } - else { - einfo = ""; - elen = 0; - } - if (EXEC_TAG()) goto error; - if (eclass == rb_eRuntimeError && elen == 0) { - warn_print(": unhandled exception\n"); - } - else { - VALUE epath; - epath = rb_class_name(eclass); - if (elen == 0) { - warn_print(": "); - warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath)); - warn_print("\n"); - } - else { - char *tail = 0; - long len = elen; +#include "eval_error.h" +#include "eval_method.h" +#include "eval_safe.h" +#include "eval_jump.h" - if (RSTRING_PTR(epath)[0] == '#') epath = 0; - if (tail = memchr(einfo, '\n', elen)) { - len = tail - einfo; - tail++; /* skip newline */ - } - warn_print(": "); - warn_print2(einfo, len); - if (epath) { - warn_print(" ("); - warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath)); - warn_print(")\n"); - } - if (tail) { - warn_print2(tail, elen-len-1); - } - } - } - - if (!NIL_P(errat)) { - long i; - -#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) -#define TRACE_HEAD 8 -#define TRACE_TAIL 5 - for (i=1; i<RARRAY_LEN(errat); i++) { - if (TYPE(RARRAY_PTR(errat)[i]) == T_STRING) { - warn_printf("\tfrom %s\n", RSTRING_PTR(RARRAY_PTR(errat)[i])); - } - if (i == TRACE_HEAD && RARRAY_LEN(errat) > TRACE_MAX) { - warn_printf("\t ... %ld levels...\n", - RARRAY_LEN(errat) - TRACE_HEAD - TRACE_TAIL); - i = RARRAY_LEN(errat) - TRACE_TAIL; - } - } - } - error: - POP_TAG(); -} +/* initialize ruby */ #if defined(__APPLE__) #define environ (*_NSGetEnviron()) @@ -1321,45 +83,24 @@ extern char **environ; #endif char **rb_origenviron; -void rb_call_inits(void); -void Init_stack(VALUE*); -void Init_heap(void); -void Init_ext(void); +jmp_buf function_call_may_return_twice_jmp_buf; +int function_call_may_return_twice_false = 0; -#ifdef HAVE_NATIVETHREAD -static rb_nativethread_t ruby_thid; -int -is_ruby_native_thread(void) -{ - return NATIVETHREAD_EQUAL(ruby_thid, NATIVETHREAD_CURRENT()); -} +void rb_call_inits _((void)); +void Init_stack _((VALUE *)); +void Init_heap _((void)); +void Init_ext _((void)); +void Init_yarv(void); -# ifdef HAVE_NATIVETHREAD_KILL void -ruby_native_thread_kill(int sig) -{ - NATIVETHREAD_KILL(ruby_thid, sig); -} -# endif -#endif - -NORETURN(static void rb_thread_start_1(void)); - -void -ruby_init(void) +ruby_init() { static int initialized = 0; - static struct FRAME frame; int state; if (initialized) return; initialized = 1; -#ifdef HAVE_NATIVETHREAD - ruby_thid = NATIVETHREAD_CURRENT(); -#endif - - ruby_frame = top_frame = &frame; #ifdef __MACOS__ rb_origenviron = 0; @@ -1367,155 +108,53 @@ ruby_init(void) rb_origenviron = environ; #endif - Init_stack((void*)&state); + Init_stack((void *)&state); + Init_yarv(); Init_heap(); - PUSH_SCOPE(); - top_scope = ruby_scope; - /* default visibility is private at toplevel */ - VIS_SET(VIS_PRIVATE); PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { rb_call_inits(); - ruby_frame->self = ruby_top_self; - ruby_top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0); - ruby_cref = ruby_top_cref; - rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self)); + #ifdef __MACOS__ _macruby_init(); #elif defined(__VMS) _vmsruby_init(); #endif + ruby_prog_init(); ALLOW_INTS; } - POP_TAG(); + POP_TAG_INIT(); + if (state) { error_print(); exit(EXIT_FAILURE); } - POP_SCOPE(); - ruby_scope = top_scope; - top_scope->flags &= ~SCOPE_NOSTACK; ruby_running = 1; } -static VALUE -eval_node(VALUE self, NODE *node) -{ - if (!node) return Qnil; - if (nd_type(node) == NODE_PRELUDE) { - rb_eval(self, node->nd_head); - node = node->nd_body; - } - if (!node) return Qnil; - return rb_eval(self, node); -} - -int ruby_in_eval; - -static void rb_thread_cleanup(void); -static void rb_thread_wait_other_threads(void); - -static int thread_set_raised(void); -static int thread_reset_raised(void); - -static int thread_no_ensure _((void)); - -static VALUE exception_error; -static VALUE sysstack_error; - -static int -sysexit_status(VALUE err) -{ - VALUE st = rb_iv_get(err, "status"); - return NUM2INT(st); -} - -static int -error_handle(int ex) -{ - int status = EXIT_FAILURE; - - if (thread_set_raised()) return EXIT_FAILURE; - switch (ex & TAG_MASK) { - case 0: - status = EXIT_SUCCESS; - break; - - case TAG_RETURN: - error_pos(); - warn_print(": unexpected return\n"); - break; - case TAG_NEXT: - error_pos(); - warn_print(": unexpected next\n"); - break; - case TAG_BREAK: - error_pos(); - warn_print(": unexpected break\n"); - break; - case TAG_REDO: - error_pos(); - warn_print(": unexpected redo\n"); - break; - case TAG_RETRY: - error_pos(); - warn_print(": retry outside of rescue clause\n"); - break; - case TAG_THROW: - if (prot_tag && prot_tag->frame && prot_tag->frame->node) { - NODE *tag = prot_tag->frame->node; - warn_printf("%s:%d: uncaught throw\n", - tag->nd_file, nd_line(tag)); - } - else { - error_pos(); - warn_printf(": unexpected throw\n"); - } - break; - case TAG_RAISE: - case TAG_FATAL: - if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) { - status = sysexit_status(ruby_errinfo); - } - else { - error_print(); - } - break; - default: - rb_bug("Unknown longjmp status %d", ex); - break; - } - thread_reset_raised(); - return status; -} - void ruby_options(int argc, char **argv) { int state; - Init_stack((void*)&state); + Init_stack((void *)&state); PUSH_THREAD_TAG(); if ((state = EXEC_TAG()) == 0) { ruby_process_options(argc, argv); } else { - if (state == TAG_THREAD) { - rb_thread_start_1(); - } - trace_func = 0; - tracing = 0; + rb_clear_trace_func(); exit(error_handle(state)); } POP_THREAD_TAG(); } -void rb_exec_end_proc(void); +void rb_exec_end_proc _((void)); static void -ruby_finalize_0(void) +ruby_finalize_0() { PUSH_TAG(PROT_NONE); if (EXEC_TAG() == 0) { @@ -1526,13 +165,12 @@ ruby_finalize_0(void) } static void -ruby_finalize_1(void) +ruby_finalize_1() { signal(SIGINT, SIG_DFL); - ruby_errinfo = 0; + GET_THREAD()->errinfo = 0; rb_gc_call_finalizer_at_exit(); - trace_func = 0; - tracing = 0; + rb_clear_trace_func(); } void @@ -1546,30 +184,38 @@ int ruby_cleanup(int ex) { int state; - volatile VALUE err = ruby_errinfo; + volatile VALUE err = GET_THREAD()->errinfo; + yarv_vm_t *vm = GET_THREAD()->vm; - ruby_safe_level = 0; - Init_stack((void*)&state); + /* th->errinfo contains a NODE while break'ing */ + if (RTEST(err) && (TYPE(err) != T_NODE) && + rb_obj_is_kind_of(err, rb_eSystemExit)) { + vm->exit_code = NUM2INT(rb_iv_get(err, "status")); + } + else { + vm->exit_code = 0; + } + + GET_THREAD()->safe_level = 0; + Init_stack((void *)&state); PUSH_THREAD_TAG(); if ((state = EXEC_TAG()) == 0) { + if (GET_THREAD()->errinfo) { + err = GET_THREAD()->errinfo; + } ruby_finalize_0(); - rb_thread_cleanup(); - rb_thread_wait_other_threads(); - } - else if (state == TAG_THREAD) { - rb_thread_start_1(); } else if (ex == 0) { ex = state; } - ruby_errinfo = err; + rb_thread_terminate_all(); + GET_THREAD()->errinfo = err; ex = error_handle(ex); ruby_finalize_1(); POP_THREAD_TAG(); - if (err && rb_obj_is_kind_of(err, rb_eSystemExit)) { - VALUE st = rb_iv_get(err, "status"); - return NUM2INT(st); + if (vm->exit_code) { + return vm->exit_code; } return ex; } @@ -1577,70 +223,57 @@ ruby_cleanup(int ex) extern NODE *ruby_eval_tree; static int -ruby_exec_internal(void) +ruby_exec_internal() { int state; - - PUSH_THREAD_TAG(); - /* default visibility is private at toplevel */ - VIS_SET(VIS_PRIVATE); + VALUE val; + PUSH_TAG(0); if ((state = EXEC_TAG()) == 0) { - eval_node(ruby_top_self, ruby_eval_tree); + GET_THREAD()->base_block = 0; + val = yarvcore_eval_parsed(ruby_eval_tree, + rb_str_new2(ruby_sourcefile)); } - else if (state == TAG_THREAD) { - rb_thread_start_1(); - } - POP_THREAD_TAG(); + POP_TAG(); return state; } int -ruby_exec(void) +ruby_exec() { volatile NODE *tmp; - Init_stack((void*)&tmp); + Init_stack((void *)&tmp); return ruby_exec_internal(); } void -ruby_stop(int ex) +ruby_stop(ex) + int ex; { exit(ruby_cleanup(ex)); } void -ruby_run(void) +ruby_run() { int state; static int ex; - if (ruby_nerrs > 0) exit(EXIT_FAILURE); - state = ruby_exec(); - if (state && !ex) ex = state; - ruby_stop(ex); -} + if (ruby_nerrs > 0) { + exit(EXIT_FAILURE); + } -static void -compile_error(const char *at) -{ - VALUE str; + state = ruby_exec(); - ruby_nerrs = 0; - str = rb_str_buf_new2("compile error"); - if (at) { - rb_str_buf_cat2(str, " in "); - rb_str_buf_cat2(str, at); - } - rb_str_buf_cat(str, "\n", 1); - if (!NIL_P(ruby_errinfo)) { - rb_str_append(str, rb_obj_as_string(ruby_errinfo)); + if (state && !ex) { + ex = state; } - rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str)); + ruby_stop(ex); } VALUE -rb_eval_string(const char *str) +rb_eval_string(str) + const char *str; { VALUE v; NODE *oldsrc = ruby_current_node; @@ -1654,13 +287,17 @@ rb_eval_string(const char *str) } VALUE -rb_eval_string_protect(const char *str, int *state) +rb_eval_string_protect(str, state) + const char *str; + int *state; { - return rb_protect((VALUE (*)(VALUE))rb_eval_string, (VALUE)str, state); + return rb_protect((VALUE (*)_((VALUE)))rb_eval_string, (VALUE)str, state); } VALUE -rb_eval_string_wrap(const char *str, int *state) +rb_eval_string_wrap(str, state) + const char *str; + int *state; { int status; VALUE self = ruby_top_self; @@ -1669,16 +306,10 @@ rb_eval_string_wrap(const char *str, int *state) ruby_top_self = rb_obj_clone(ruby_top_self); rb_extend_object(ruby_top_self, ruby_wrapper); - PUSH_FRAME(Qfalse); - ruby_frame->self = self; - PUSH_CREF(ruby_wrapper = rb_module_new()); - PUSH_SCOPE(); val = rb_eval_string_protect(str, &status); ruby_top_self = self; - POP_SCOPE(); - POP_FRAME(); ruby_wrapper = wrapper; if (state) { *state = status; @@ -1689,176 +320,45 @@ rb_eval_string_wrap(const char *str, int *state) return val; } -NORETURN(static void localjump_error(const char*, VALUE, int, VALUE)); -static void -localjump_error(const char *mesg, VALUE value, int reason, VALUE bt) -{ - VALUE exc = rb_exc_new2(rb_eLocalJumpError, mesg); - ID id; - - rb_iv_set(exc, "@exit_value", value); - switch (reason) { - case TAG_BREAK: - id = rb_intern("break"); break; - case TAG_REDO: - id = rb_intern("redo"); break; - case TAG_RETRY: - id = rb_intern("retry"); break; - case TAG_NEXT: - id = rb_intern("next"); break; - case TAG_RETURN: - id = rb_intern("return"); break; - default: - id = rb_intern("yield"); break; - } - rb_iv_set(exc, "@reason", ID2SYM(id)); - if (bt) set_backtrace(exc, bt); - rb_exc_raise(exc); -} - -/* - * call_seq: - * local_jump_error.exit_value => obj - * - * Returns the exit value associated with this +LocalJumpError+. - */ -static VALUE -localjump_xvalue(VALUE exc) -{ - return rb_iv_get(exc, "@exit_value"); -} - -/* - * call-seq: - * local_jump_error.reason => symbol - * - * The reason this block was terminated: - * :break, :redo, :retry, :next, :return, or :yield. - */ - -static VALUE -localjump_reason(VALUE exc) -{ - return rb_iv_get(exc, "@reason"); -} - -NORETURN(static void jump_tag_but_local_jump(int,VALUE)); -static void -jump_tag_but_local_jump(int state, VALUE val) -{ - - if (val == Qundef) val = prot_tag->retval; - switch (state) { - case 0: - break; - case TAG_RETURN: - localjump_error("unexpected return", val, state, 0); - break; - case TAG_BREAK: - localjump_error("unexpected break", val, state, 0); - break; - case TAG_NEXT: - localjump_error("unexpected next", val, state, 0); - break; - case TAG_REDO: - localjump_error("unexpected redo", Qnil, state, 0); - break; - case TAG_RETRY: - localjump_error("retry outside of rescue clause", Qnil, state, 0); - break; - default: - break; - } - JUMP_TAG(state); -} - VALUE rb_eval_cmd(VALUE cmd, VALUE arg, int level) { int state; VALUE val = Qnil; /* OK */ - struct SCOPE *saved_scope; - volatile int safe = ruby_safe_level; + volatile int safe = rb_safe_level(); if (OBJ_TAINTED(cmd)) { level = 4; } if (TYPE(cmd) != T_STRING) { + PUSH_TAG(PROT_NONE); - ruby_safe_level = level; + rb_set_safe_level_force(level); if ((state = EXEC_TAG()) == 0) { - val = rb_funcall2(cmd, rb_intern("yield"), - RARRAY_LEN(arg), RARRAY_PTR(arg)); + val = + rb_funcall2(cmd, rb_intern("call"), RARRAY_LEN(arg), + RARRAY_PTR(arg)); } - ruby_safe_level = safe; POP_TAG(); - if (state) JUMP_TAG(state); - return val; - } - saved_scope = ruby_scope; - ruby_scope = top_scope; - PUSH_FRAME(Qfalse); - ruby_frame->self = ruby_top_self; - PUSH_CREF(ruby_wrapper ? ruby_wrapper : rb_cObject); + rb_set_safe_level_force(safe); - ruby_safe_level = level; + if (state) + JUMP_TAG(state); + return val; + } PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { val = eval(ruby_top_self, cmd, Qnil, 0, 0); } - if (ruby_scope->flags & SCOPE_DONT_RECYCLE) - scope_dup(saved_scope); - ruby_scope = saved_scope; - ruby_safe_level = safe; POP_TAG(); - POP_FRAME(); - jump_tag_but_local_jump(state, val); + rb_set_safe_level_force(safe); + th_jump_tag_but_local_jump(state, val); return val; } -#define ruby_cbase (ruby_cref->nd_clss) -VALUE -ruby_current_class_object() -{ - return ruby_cbase; -} - -static VALUE -ev_const_defined(ID id, VALUE self) -{ - VALUE cbase = ruby_cbase; - if (NIL_P(cbase)) cbase = rb_obj_class(self); - return rb_const_defined_fallback(cbase, id, ruby_cref->nd_next); -} - -static VALUE -ev_const_get(ID id, VALUE self) -{ - VALUE cbase = ruby_cbase; - if (NIL_P(cbase)) cbase = rb_obj_class(self); - return rb_const_get_fallback(cbase, id, ruby_cref->nd_next); -} - -static VALUE -cvar_cbase(void) -{ - NODE *cref = ruby_cref; - - while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) { - cref = cref->nd_next; - if (!cref->nd_next) { - rb_warn("class variable access from toplevel singleton method"); - } - } - if (NIL_P(cref->nd_clss)) { - rb_raise(rb_eTypeError, "no class variables available"); - } - return cref->nd_clss; -} - /* * call-seq: * Module.nesting => array @@ -1877,15 +377,15 @@ cvar_cbase(void) static VALUE rb_mod_nesting(void) { - NODE *cbase = ruby_cref; VALUE ary = rb_ary_new(); + NODE *cref = ruby_cref(); - while (cbase && cbase->nd_next) { - if (!NIL_P(cbase->nd_clss)) rb_ary_push(ary, cbase->nd_clss); - cbase = cbase->nd_next; - } - if (ruby_wrapper && RARRAY_LEN(ary) == 0) { - rb_ary_push(ary, ruby_wrapper); + while (cref && cref->nd_next) { + VALUE klass = cref->nd_clss; + if (!NIL_P(klass)) { + rb_ary_push(ary, klass); + } + cref = cref->nd_next; } return ary; } @@ -1907,22 +407,28 @@ rb_mod_nesting(void) static VALUE rb_mod_s_constants(int argc, VALUE *argv, VALUE mod) { - NODE *cbase = ruby_cref; + NODE *cref = ruby_cref(); + VALUE klass; + VALUE cbase = 0; void *data = 0; if (argc > 0) { return rb_mod_constants(argc, argv, rb_cModule); } - while (cbase) { - if (!NIL_P(cbase->nd_clss)) { - data = rb_mod_const_at(cbase->nd_clss, data); + while (cref) { + klass = cref->nd_clss; + if (!NIL_P(klass)) { + data = rb_mod_const_at(cref->nd_clss, data); + if (!cbase) { + cbase = klass; + } } - cbase = cbase->nd_next; + cref = cref->nd_next; } - if (NIL_P(ruby_cbase)) { - data = rb_mod_const_of(ruby_cbase, data); + if (cbase) { + data = rb_mod_const_of(cbase, data); } return rb_const_list(data); } @@ -1930,219 +436,26 @@ rb_mod_s_constants(int argc, VALUE *argv, VALUE mod) void rb_frozen_class_p(VALUE klass) { - const char *desc = "something(?!)"; + char *desc = "something(?!)"; if (OBJ_FROZEN(klass)) { if (FL_TEST(klass, FL_SINGLETON)) desc = "object"; else { switch (TYPE(klass)) { - case T_MODULE: - case T_ICLASS: - desc = "module"; break; - case T_CLASS: - desc = "class"; break; + case T_MODULE: + case T_ICLASS: + desc = "module"; + break; + case T_CLASS: + desc = "class"; + break; } } rb_error_frozen(desc); } } -void -rb_undef(VALUE klass, ID id) -{ - VALUE origin; - NODE *body; - - if (ruby_cbase == rb_cObject && klass == rb_cObject) { - rb_secure(4); - } - if (ruby_safe_level >= 4 && !OBJ_TAINTED(klass)) { - rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); - } - rb_frozen_class_p(klass); - if (id == object_id || id == __send || id == __send_bang || id == init) { - rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); - } - body = search_method(klass, id, &origin, LOOKUP_NOSKIP, 0); - if (!body || !body->nd_body) { - const char *s0 = " class"; - VALUE c = klass; - - if (FL_TEST(c, FL_SINGLETON)) { - VALUE obj = rb_iv_get(klass, "__attached__"); - - switch (TYPE(obj)) { - case T_MODULE: - case T_CLASS: - c = obj; - s0 = ""; - } - } - else if (TYPE(c) == T_MODULE) { - s0 = " module"; - } - rb_name_error(id, "undefined method `%s' for%s `%s'", - rb_id2name(id),s0,rb_class2name(c)); - } - rb_add_method(klass, id, 0, NOEX_PUBLIC); - if (FL_TEST(klass, FL_SINGLETON)) { - rb_funcall(rb_iv_get(klass, "__attached__"), - singleton_undefined, 1, ID2SYM(id)); - } - else { - rb_funcall(klass, undefined, 1, ID2SYM(id)); - } -} - -/* - * call-seq: - * undef_method(symbol) => self - * - * Prevents the current class from responding to calls to the named - * method. Contrast this with <code>remove_method</code>, which deletes - * the method from the particular class; Ruby will still search - * superclasses and mixed-in modules for a possible receiver. - * - * class Parent - * def hello - * puts "In parent" - * end - * end - * class Child < Parent - * def hello - * puts "In child" - * end - * end - * - * - * c = Child.new - * c.hello - * - * - * class Child - * remove_method :hello # remove from child, still in parent - * end - * c.hello - * - * - * class Child - * undef_method :hello # prevent any calls to 'hello' - * end - * c.hello - * - * <em>produces:</em> - * - * In child - * In parent - * prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError) - */ - -static VALUE -rb_mod_undef_method(int argc, VALUE *argv, VALUE mod) -{ - int i; - - for (i=0; i<argc; i++) { - rb_undef(mod, rb_to_id(argv[i])); - } - return mod; -} - -void -rb_alias(VALUE klass, ID name, ID def) -{ - VALUE origin; - NODE *orig, *body, *node; - VALUE singleton = 0; - - rb_frozen_class_p(klass); - if (name == def) return; - if (klass == rb_cObject) { - rb_secure(4); - } - orig = search_method(klass, def, &origin, LOOKUP_NOSKIP, 0); - if (!orig || !orig->nd_body) { - if (TYPE(klass) == T_MODULE) { - orig = search_method(rb_cObject, def, &origin, LOOKUP_NOSKIP, 0); - } - } - if (!orig || !orig->nd_body) { - raise_undef(klass, def); - } - if (FL_TEST(klass, FL_SINGLETON)) { - singleton = rb_iv_get(klass, "__attached__"); - } - body = orig->nd_body; - orig->nd_cnt++; - if (nd_type(body) == NODE_FBODY) { /* was alias */ - def = body->nd_mid; - origin = body->nd_orig; - body = body->nd_head; - } - - rb_clear_cache_by_id(name); - if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *)&node)) { - if (node->nd_cnt == 0 && node->nd_body) { - rb_warning("discarding old %s", rb_id2name(name)); - } - } - st_insert(RCLASS(klass)->m_tbl, name, - (st_data_t)NEW_METHOD(NEW_FBODY(body, def, origin), - NOEX_WITH_SAFE(orig->nd_noex))); - if (singleton) { - rb_funcall(singleton, singleton_added, 1, ID2SYM(name)); - } - else { - rb_funcall(klass, added, 1, ID2SYM(name)); - } -} - -/* - * call-seq: - * alias_method(new_name, old_name) => self - * - * Makes <i>new_name</i> a new copy of the method <i>old_name</i>. This can - * be used to retain access to methods that are overridden. - * - * module Mod - * alias_method :orig_exit, :exit - * def exit(code=0) - * puts "Exiting with code #{code}" - * orig_exit(code) - * end - * end - * include Mod - * exit(99) - * - * <em>produces:</em> - * - * Exiting with code 99 - */ - -static VALUE -rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) -{ - rb_alias(mod, rb_to_id(newname), rb_to_id(oldname)); - return mod; -} - -static NODE* -copy_node_scope(NODE *node, NODE *rval) -{ - NODE *cref = NEW_NODE(NODE_CREF,rval->nd_clss,0,rval->nd_next); - NODE *copy = NEW_NODE(NODE_SCOPE,0,cref,node->nd_next); - - if (node->nd_tbl) { - copy->nd_tbl = ALLOC_N(ID, node->nd_tbl[0]+1); - MEMCPY(copy->nd_tbl, node->nd_tbl, ID, node->nd_tbl[0]+1); - } - else { - copy->nd_tbl = 0; - } - return copy; -} - #ifdef C_ALLOCA # define TMP_PROTECT NODE * volatile tmp__protect_tmp=0 # define TMP_ALLOC(n) \ @@ -2154,279 +467,19 @@ copy_node_scope(NODE *node, NODE *rval) # define TMP_ALLOC(n) ALLOCA_N(VALUE,n) #endif -#define CALLARGS int argc; VALUE *argv; struct BLOCK *block = 0, _block -#define SETUP_ARGS0(anode,extra) do {\ - NODE *n = anode, *bpass = 0;\ - if (n && nd_type(n) == NODE_BLOCK_PASS) {\ - bpass = n;\ - n = n->nd_head;\ - }\ - if (!n) {\ - argc = 0;\ - argv = 0;\ - }\ - else if (nd_type(n) == NODE_ARRAY) {\ - argc=n->nd_alen;\ - if (argc > 0) {\ - int i;\ - argv = TMP_ALLOC(argc+extra);\ - for (i=0;i<argc;i++) {\ - argv[i] = rb_eval(self,n->nd_head);\ - n=n->nd_next;\ - }\ - }\ - else {\ - argc = 0;\ - argv = 0;\ - }\ - }\ - else {\ - VALUE args = rb_eval(self,n);\ - if (TYPE(args) != T_ARRAY)\ - args = rb_ary_to_ary(args);\ - argc = RARRAY_LEN(args);\ - argv = TMP_ALLOC(argc+extra);\ - MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);\ - }\ - if (bpass) {\ - volatile VALUE save_block = rb_eval(self, bpass->nd_body); \ - block = passing_block(save_block, &_block);\ - }\ -} while (0) - -#define SETUP_ARGS(anode) SETUP_ARGS0(anode,0) - -#define ZSUPER_ARGS() do {\ - argc = ruby_frame->argc;\ - if (argc && DMETHOD_P()) {\ - if (TYPE(RBASIC(ruby_scope)->klass) != T_ARRAY ||\ - RARRAY_LEN(RBASIC(ruby_scope)->klass) != argc) {\ - rb_raise(rb_eRuntimeError, \ - "super: specify arguments explicitly");\ - }\ - argv = RARRAY_PTR(RBASIC(ruby_scope)->klass);\ - }\ - else {\ - argv = ruby_scope->local_vars + 2;\ - }\ -} while (0) - #define MATCH_DATA *rb_svar(node->nd_cnt) -static const char* is_defined(VALUE, NODE*, char*, int); - -static char* -arg_defined(VALUE self, NODE *node, char *buf, char *type) -{ - int argc; - int i; - - if (!node) return type; /* no args */ - if (nd_type(node) == NODE_ARRAY) { - argc=node->nd_alen; - if (argc > 0) { - for (i=0;i<argc;i++) { - if (!is_defined(self, node->nd_head, buf, 0)) - return 0; - node = node->nd_next; - } - } - } - else if (!is_defined(self, node, buf, 0)) { - return 0; - } - return type; -} - -static const char* -is_defined(VALUE self, NODE *node /* OK */, char *buf, int noeval) -{ - VALUE val; /* OK */ - int state, noex; - static const char *ex = "expression"; - - if (!node) return ex; - switch (nd_type(node)) { - case NODE_SUPER: - case NODE_ZSUPER: - if (ruby_frame->this_func == 0) return 0; - else if (ruby_frame->this_class == 0) return 0; - val = ruby_frame->this_class; - if (method_exists(RCLASS(val)->super, ruby_frame->this_func, LOOKUP_FCALL)) { - if (nd_type(node) == NODE_SUPER) { - return arg_defined(self, node->nd_args, buf, "super"); - } - return "super"; - } - break; - - case NODE_VCALL: - case NODE_FCALL: - val = self; - noex = LOOKUP_FCALL; - goto check_bound; - - case NODE_ATTRASGN: - val = self; - if (node->nd_recv == (NODE *)1) goto check_bound; - case NODE_CALL: - if (!is_defined(self, node->nd_recv, buf, Qtrue)) return 0; - if (noeval) return ex; - noex = LOOKUP_NORMAL; - val = rb_eval(self, node->nd_recv); - check_bound: - { - ID id = node->nd_mid; - - val = CLASS_OF(val); - if (!rb_get_method_body(&val, &id, &noex)) - return 0; - if (nd_type(node) == NODE_CALL) { - if ((noex & NOEX_PRIVATE)) return 0; - if ((noex & NOEX_PROTECTED) && - !rb_obj_is_kind_of(self, rb_class_real(val))) - return 0; - } - return arg_defined(self, node->nd_args, buf, - nd_type(node) == NODE_ATTRASGN ? - "assignment" : "method"); - } - break; - - case NODE_MATCH2: - case NODE_MATCH3: - return "method"; - - case NODE_YIELD: - if (rb_block_given_p()) { - return "yield"; - } - break; - - case NODE_SELF: - return "self"; - - case NODE_NIL: - return "nil"; - - case NODE_TRUE: - return "true"; - - case NODE_FALSE: - return "false"; - - case NODE_ATTRSET: - case NODE_OP_ASGN1: - case NODE_OP_ASGN2: - case NODE_MASGN: - case NODE_LASGN: - case NODE_DASGN: - case NODE_DASGN_CURR: - case NODE_GASGN: - case NODE_IASGN: - case NODE_CDECL: - case NODE_CVDECL: - case NODE_CVASGN: - return "assignment"; - - case NODE_LVAR: - return "local-variable"; - case NODE_DVAR: - return "local-variable(in-block)"; - - case NODE_GVAR: - if (rb_gvar_defined(node->nd_entry)) { - return "global-variable"; - } - break; - - case NODE_IVAR: - if (rb_ivar_defined(self, node->nd_vid)) { - return "instance-variable"; - } - break; - - case NODE_CONST: - if (ev_const_defined(node->nd_vid, self)) { - return "constant"; - } - break; - - case NODE_CVAR: - if (rb_cvar_defined(cvar_cbase(), node->nd_vid)) { - return "class variable"; - } - break; - - case NODE_COLON2: - if (!is_defined(self, node->nd_recv, buf, Qtrue)) return 0; - if (noeval) return ex; - val = rb_eval(self, node->nd_recv); - switch (TYPE(val)) { - case T_CLASS: - case T_MODULE: - if (rb_const_defined_from(val, node->nd_mid)) - return "constant"; - break; - default: - if (rb_method_boundp(CLASS_OF(val), node->nd_mid, Qtrue)) { - return "method"; - } - } - break; - - case NODE_COLON3: - if (rb_const_defined_from(rb_cObject, node->nd_mid)) { - return "constant"; - } - break; - - case NODE_NTH_REF: - if (RTEST(rb_reg_nth_defined(node->nd_nth, MATCH_DATA))) { - if (!buf) return ex; - sprintf(buf, "$%d", (int)node->nd_nth); - return buf; - } - break; - - case NODE_BACK_REF: - if (RTEST(rb_reg_nth_defined(0, MATCH_DATA))) { - if (!buf) return ex; - sprintf(buf, "$%c", (char)node->nd_nth); - return buf; - } - break; - - default: - PUSH_TAG(PROT_NONE); - if ((state = EXEC_TAG()) == 0) { - rb_eval(self, node); - } - POP_TAG(); - if (!state) { - return ex; - } - ruby_errinfo = Qnil; - break; - } - return 0; -} - -static int handle_rescue(VALUE,NODE*); - -static void blk_free(struct BLOCK *data); - static VALUE -rb_obj_is_proc(VALUE proc) +rb_obj_is_proc(proc) + VALUE proc; { - if (TYPE(proc) == T_DATA && RDATA(proc)->dfree == (RUBY_DATA_FUNC)blk_free) { - return Qtrue; - } - return Qfalse; + return yarv_obj_is_proc(proc); } void -rb_add_event_hook(rb_event_hook_func_t func, rb_event_t events) +rb_add_event_hook(func, events) + rb_event_hook_func_t func; + rb_event_t events; { rb_event_hook_t *hook; @@ -2440,7 +493,6 @@ rb_add_event_hook(rb_event_hook_func_t func, rb_event_t events) int rb_remove_event_hook(rb_event_hook_func_t func) { - rb_event_hook_t *prev, *hook; prev = NULL; @@ -2462,6 +514,12 @@ rb_remove_event_hook(rb_event_hook_func_t func) return -1; } +static void +rb_clear_trace_func(void) +{ + // TODO: fix me +} + /* * call-seq: * set_trace_func(proc) => proc @@ -2511,16 +569,18 @@ set_trace_func(VALUE obj, VALUE trace) { rb_event_hook_t *hook; - rb_secure(4); if (NIL_P(trace)) { - trace_func = 0; + rb_clear_trace_func(); rb_remove_event_hook(call_trace_func); return Qnil; } if (!rb_obj_is_proc(trace)) { rb_raise(rb_eTypeError, "trace_func needs to be Proc"); } - trace_func = trace; + + // register trace func + // trace_func = trace; + for (hook = event_hooks; hook; hook = hook->next) { if (hook->func == call_trace_func) return trace; @@ -2529,7 +589,7 @@ set_trace_func(VALUE obj, VALUE trace) return trace; } -static const char * +static char * get_event_name(rb_event_t event) { switch (event) { @@ -2555,31 +615,31 @@ get_event_name(rb_event_t event) } static void -call_trace_func(rb_event_t event, NODE *node, VALUE self, ID id, VALUE klass /* OK */) +call_trace_func(rb_event_t event, NODE *node, VALUE self, ID id, VALUE klass) { + // TODO: fix me +#if 0 int state, raised; - struct FRAME *prev; NODE *node_save; VALUE srcfile; - const char *event_name; + char *event_name; - if (!trace_func) return; - if (tracing) return; - if (id == ID_ALLOCATOR) return; - if (!node && ruby_sourceline == 0) return; + if (!trace_func) + return; + if (tracing) + return; + if (id == ID_ALLOCATOR) + return; + if (!node && ruby_sourceline == 0) + return; if (!(node_save = ruby_current_node)) { node_save = NEW_BEGIN(0); } tracing = 1; - prev = ruby_frame; - PUSH_FRAME(Qfalse); - *ruby_frame = *prev; - ruby_frame->prev = prev; if (node) { ruby_current_node = node; - ruby_frame->node = node; ruby_sourcefile = node->nd_file; ruby_sourceline = nd_line(node); } @@ -2588,1443 +648,42 @@ call_trace_func(rb_event_t event, NODE *node, VALUE self, ID id, VALUE klass /* klass = RBASIC(klass)->klass; } else if (FL_TEST(klass, FL_SINGLETON)) { - klass = rb_iv_get(klass, "__attached__"); + klass = self; } } PUSH_TAG(PROT_NONE); - raised = thread_reset_raised(); + raised = thread_reset_raised(th); if ((state = EXEC_TAG()) == 0) { - srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)"); + srcfile = rb_str_new2(ruby_sourcefile ? ruby_sourcefile : "(ruby)"); event_name = get_event_name(event); proc_invoke(trace_func, rb_ary_new3(6, rb_str_new2(event_name), srcfile, INT2FIX(ruby_sourceline), - id?ID2SYM(id):Qnil, + id ? ID2SYM(id) : Qnil, self ? rb_f_binding(self) : Qnil, - klass?klass:Qnil), - Qundef, 0, 0); + klass ? klass : Qnil), Qundef, 0); } - if (raised) thread_set_raised(); + if (raised) + thread_set_raised(th); POP_TAG(); - POP_FRAME(); tracing = 0; ruby_current_node = node_save; SET_CURRENT_SOURCE(); - if (state) JUMP_TAG(state); -} - -static VALUE -splat(VALUE v, int strict) -{ - VALUE tmp; - - if (v == Qundef) return rb_ary_new2(0); - tmp = rb_check_convert_type(v, T_ARRAY, "Array", "to_splat"); - if (NIL_P(tmp)) { - if (strict) { - rb_raise(rb_eTypeError, "failed to splat"); - } - return rb_ary_new3(1, v); - } - return tmp; -} - -static VALUE -svalue_to_avalue(VALUE v) -{ - return splat(v, Qfalse); -} - -static VALUE -splat_value(VALUE v) -{ - return splat(v, Qtrue); -} - -static VALUE -class_prefix(VALUE self, NODE *cpath) -{ - if (!cpath) { - rb_bug("class path missing"); - } - if (cpath->nd_head) { - VALUE c = rb_eval(self, cpath->nd_head); - switch (TYPE(c)) { - case T_CLASS: - case T_MODULE: - break; - default: - rb_raise(rb_eTypeError, "%s is not a class/module", - RSTRING_PTR(rb_obj_as_string(c))); - } - return c; - } - else if (nd_type(cpath) == NODE_COLON2) { - return ruby_cbase; - } - else if (ruby_wrapper) { - return ruby_wrapper; - } - else { - return rb_cObject; - } -} - -#define return_value(v) do {\ - if ((prot_tag->retval = (v)) == Qundef) {\ - prot_tag->retval = Qnil;\ - }\ -} while (0) - -NORETURN(static void return_jump(VALUE)); -NORETURN(static void break_jump(VALUE)); -NORETURN(static void next_jump(VALUE)); -NORETURN(static void unknown_node(NODE * volatile)); - -static VALUE call_super(int, const VALUE*, struct BLOCK*); -static VALUE call_super_0(VALUE, VALUE, ID mid, int argc, const VALUE*, struct BLOCK *); - -static void -unknown_node(NODE *volatile node) -{ - ruby_current_node = 0; - if (node->flags == 0) { - rb_bug("terminated node (%p)", node); - } - else if (BUILTIN_TYPE(node) != T_NODE) { - rb_bug("not a node 0x%02lx (%p)", BUILTIN_TYPE(node), node); - } - else { - rb_bug("unknown node type %d (%p)", nd_type(node), node); - } -} - -static int -when_cond(VALUE v1, VALUE v2) -{ - if (v1 == Qundef) { - return RTEST(v2); - } - return RTEST(rb_funcall2(v2, eqq, 1, &v1)); -} - -static int -when_check(NODE *tag, VALUE val, VALUE self) -{ - VALUE elm; - long i; - - switch (nd_type(tag)) { - case NODE_ARRAY: - while (tag) { - elm = rb_eval(self, tag->nd_head); - if (when_cond(val, elm)) { - return Qtrue; - } - tag = tag->nd_next; - } - break; - case NODE_SPLAT: - tag = tag->nd_head; - splat: - elm = splat_value(rb_eval(self, tag)); - for (i=0; i<RARRAY_LEN(elm); i++) { - if (when_cond(val, RARRAY_PTR(elm)[i])) { - return Qtrue; - } - } - break; - case NODE_ARGSCAT: - if (when_check(tag->nd_head, val, self)) return Qtrue; - tag = tag->nd_body; - goto splat; - case NODE_ARGSPUSH: - if (when_check(tag->nd_head, val, self)) return Qtrue; - if (when_cond(val, rb_eval(self, tag->nd_body))) return Qtrue; - default: - if (when_cond(val, rb_eval(self, tag))) return Qtrue; - break; - } - return Qfalse; -} - -static VALUE -rb_eval(VALUE self, NODE *n) -{ - NODE * volatile contnode = 0; - NODE * volatile node = n; - int state; - volatile VALUE result = Qnil; - -#define RETURN(v) do { \ - result = (v); \ - goto finish; \ -} while (0) - - again: - if (!node) RETURN(Qnil); - - ruby_current_node = node; - if (node->flags & NODE_NEWLINE) { - EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, - ruby_frame->this_func, - ruby_frame->this_class); - } - switch (nd_type(node)) { - case NODE_BLOCK: - if (contnode) { - result = rb_eval(self, node); - break; - } - contnode = node->nd_next; - node = node->nd_head; - goto again; - - case NODE_POSTEXE: - PUSH_FRAME(Qtrue); - PUSH_BLOCK(ruby_frame->block, 0, node->nd_body); - rb_f_END(); - POP_BLOCK(); - POP_FRAME(); - nd_set_type(node, NODE_NIL); /* exec just once */ - result = Qnil; - break; - - /* begin .. end without clauses */ - case NODE_BEGIN: - node = node->nd_body; - goto again; - - /* nodes for speed-up(default match) */ - case NODE_MATCH: - result = rb_reg_match2(node->nd_lit); - break; - - /* nodes for speed-up(literal match) */ - case NODE_MATCH2: - { - VALUE l = rb_eval(self,node->nd_recv); - VALUE r = rb_eval(self,node->nd_value); - result = rb_reg_match(l, r); - } - break; - - /* nodes for speed-up(literal match) */ - case NODE_MATCH3: - { - VALUE r = rb_eval(self,node->nd_recv); - VALUE l = rb_eval(self,node->nd_value); - if (TYPE(l) == T_STRING) { - result = rb_reg_match(r, l); - } - else { - result = rb_funcall(l, match, 1, r); - } - } - break; - - /* node for speed-up(top-level loop for -n/-p) */ - case NODE_OPT_N: - PUSH_TAG(PROT_LOOP); - switch (state = EXEC_TAG()) { - case 0: - opt_n_next: - while (!NIL_P(rb_gets())) { - opt_n_redo: - rb_eval(self, node->nd_body); - } - break; - - case TAG_REDO: - state = 0; - goto opt_n_redo; - case TAG_NEXT: - state = 0; - goto opt_n_next; - case TAG_BREAK: - state = 0; - default: - break; - } - POP_TAG(); - if (state) JUMP_TAG(state); - RETURN(Qnil); - - case NODE_SELF: - RETURN(self); - - case NODE_NIL: - RETURN(Qnil); - - case NODE_TRUE: - RETURN(Qtrue); - - case NODE_FALSE: - RETURN(Qfalse); - - case NODE_ERRINFO: - RETURN(ruby_errinfo); - - case NODE_IF: - EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, - ruby_frame->this_func, - ruby_frame->this_class); - if (RTEST(rb_eval(self, node->nd_cond))) { - node = node->nd_body; - } - else { - node = node->nd_else; - } - goto again; - - case NODE_CASE: - { - VALUE val = Qundef; - - if (node->nd_head) - val = rb_eval(self, node->nd_head); - node = node->nd_body; - while (node) { - if (nd_type(node) != NODE_WHEN) { - goto again; - } - EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node->nd_head, self, - ruby_frame->this_func, - ruby_frame->this_class); - if (when_check(node->nd_head, val, self)) { - node = node->nd_body; - goto again; - } - node = node->nd_next; - } - } - RETURN(Qnil); - - case NODE_WHILE: - PUSH_TAG(PROT_LOOP); - result = Qnil; - switch (state = EXEC_TAG()) { - case 0: - if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond))) - goto while_out; - do { - while_redo: - rb_eval(self, node->nd_body); - while_next: - ; - } while (RTEST(rb_eval(self, node->nd_cond))); - break; - - case TAG_REDO: - state = 0; - goto while_redo; - case TAG_NEXT: - state = 0; - goto while_next; - case TAG_BREAK: - if (TAG_DST()) { - state = 0; - result = prot_tag->retval; - } - /* fall through */ - default: - break; - } - while_out: - POP_TAG(); - if (state) JUMP_TAG(state); - RETURN(result); - - case NODE_UNTIL: - PUSH_TAG(PROT_LOOP); - result = Qnil; - switch (state = EXEC_TAG()) { - case 0: - if (node->nd_state && RTEST(rb_eval(self, node->nd_cond))) - goto until_out; - do { - until_redo: - rb_eval(self, node->nd_body); - until_next: - ; - } while (!RTEST(rb_eval(self, node->nd_cond))); - break; - - case TAG_REDO: - state = 0; - goto until_redo; - case TAG_NEXT: - state = 0; - goto until_next; - case TAG_BREAK: - if (TAG_DST()) { - state = 0; - result = prot_tag->retval; - } - /* fall through */ - default: - break; - } - until_out: - POP_TAG(); - if (state) JUMP_TAG(state); - RETURN(result); - - case NODE_LAMBDA: - PUSH_TAG(PROT_LOOP); - PUSH_FRAME(Qtrue); - PUSH_BLOCK(ruby_frame->block, node->nd_var, node->nd_body); - state = EXEC_TAG(); - result = proc_lambda(); - POP_BLOCK(); - POP_FRAME(); - POP_TAG(); - break; - - case NODE_BREAK: - break_jump(rb_eval(self, node->nd_stts)); - break; - - case NODE_NEXT: - CHECK_INTS; - next_jump(rb_eval(self, node->nd_stts)); - break; - - case NODE_REDO: - CHECK_INTS; - JUMP_TAG(TAG_REDO); - break; - - case NODE_RETRY: - CHECK_INTS; - JUMP_TAG(TAG_RETRY); - break; - - case NODE_SPLAT: - result = splat_value(rb_eval(self, node->nd_head)); - break; - - case NODE_TO_ARY: - result = rb_ary_to_ary(rb_eval(self, node->nd_head)); - break; - - case NODE_YIELD: - if (node->nd_head) { - result = rb_eval(self, node->nd_head); - ruby_current_node = node; - } - else { - result = Qundef; /* no arg */ - } - SET_CURRENT_SOURCE(); - result = rb_yield_0(result, 0, 0, node->nd_state ? YIELD_VALUES : 0); - break; - - case NODE_RESCUE: - { - volatile VALUE e_info = ruby_errinfo; - volatile int rescuing = 0; - - PUSH_TAG(PROT_NONE); - if ((state = EXEC_TAG()) == 0) { - retry_entry: - result = rb_eval(self, node->nd_head); - } - else if (rescuing) { - if (rescuing < 0) { - /* in rescue argument, just reraise */ - } - else if (state == TAG_RETRY) { - rescuing = state = 0; - ruby_errinfo = e_info; - goto retry_entry; - } - else if (state != TAG_RAISE) { - result = prot_tag->retval; - } - } - else if (state == TAG_RAISE) { - NODE *resq = node->nd_resq; - - rescuing = -1; - while (resq) { - ruby_current_node = resq; - if (handle_rescue(self, resq)) { - state = 0; - rescuing = 1; - result = rb_eval(self, resq->nd_body); - break; - } - resq = resq->nd_head; /* next rescue */ - } - } - else { - result = prot_tag->retval; - } - POP_TAG(); - if (state != TAG_RAISE) ruby_errinfo = e_info; - if (state) { - JUMP_TAG(state); - } - /* no exception raised */ - if (!rescuing && (node = node->nd_else)) { /* else clause given */ - goto again; - } - } - break; - - case NODE_ENSURE: - PUSH_TAG(PROT_NONE); - if ((state = EXEC_TAG()) == 0) { - result = rb_eval(self, node->nd_head); - } - POP_TAG(); - if (node->nd_ensr && !thread_no_ensure()) { - VALUE retval = prot_tag->retval; /* save retval */ - VALUE errinfo = ruby_errinfo; - - rb_eval(self, node->nd_ensr); - return_value(retval); - ruby_errinfo = errinfo; - } - if (state) JUMP_TAG(state); - break; - - case NODE_AND: - result = rb_eval(self, node->nd_1st); - if (!RTEST(result)) break; - node = node->nd_2nd; - goto again; - - case NODE_OR: - result = rb_eval(self, node->nd_1st); - if (RTEST(result)) break; - node = node->nd_2nd; - goto again; - - case NODE_NOT: - if (RTEST(rb_eval(self, node->nd_body))) result = Qfalse; - else result = Qtrue; - break; - - case NODE_DOT2: - case NODE_DOT3: - { - VALUE beg = rb_eval(self, node->nd_beg); - VALUE end = rb_eval(self, node->nd_end); - result = rb_range_new(beg, end, nd_type(node) == NODE_DOT3); - } - break; - - case NODE_FLIP2: /* like AWK */ - { - VALUE *flip = rb_svar(node->nd_cnt); - if (!flip) rb_bug("unexpected local variable"); - if (!RTEST(*flip)) { - if (RTEST(rb_eval(self, node->nd_beg))) { - *flip = RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue; - result = Qtrue; - } - else { - result = Qfalse; - } - } - else { - if (RTEST(rb_eval(self, node->nd_end))) { - *flip = Qfalse; - } - result = Qtrue; - } - } - break; - - case NODE_FLIP3: /* like SED */ - { - VALUE *flip = rb_svar(node->nd_cnt); - if (!flip) rb_bug("unexpected local variable"); - if (!RTEST(*flip)) { - result = RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse; - *flip = result; - } - else { - if (RTEST(rb_eval(self, node->nd_end))) { - *flip = Qfalse; - } - result = Qtrue; - } - } - break; - - case NODE_RETURN: - return_jump(rb_eval(self, node->nd_stts)); - break; - - case NODE_ARGSCAT: - { - VALUE args = rb_eval(self, node->nd_head); - result = rb_ary_concat(args, splat_value(rb_eval(self, node->nd_body))); - } - break; - - case NODE_ARGSPUSH: - { - VALUE args = rb_ary_dup(rb_eval(self, node->nd_head)); - result = rb_ary_push(args, rb_eval(self, node->nd_body)); - } - break; - - case NODE_ATTRASGN: - { - VALUE recv; - calling_scope_t scope; - CALLARGS; - TMP_PROTECT; - - if (node->nd_recv == (NODE *)1) { - recv = self; - scope = CALLING_FCALL; - } - else { - recv = rb_eval(self, node->nd_recv); - scope = CALLING_NORMAL; - } - SETUP_ARGS(node->nd_args); - - ruby_current_node = node; - SET_CURRENT_SOURCE(); - rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,block,scope,0,self); - result = argv[argc-1]; - } - break; - - case NODE_FOR: - { - VALUE recv; - int state; - struct BLOCK *block; - - PUSH_TAG(PROT_LOOP); - PUSH_BLOCK(block, node->nd_var, node->nd_body); - state = EXEC_TAG(); - if (state == 0) { - for_retry: - block->flags &= ~BLOCK_D_SCOPE; - recv = rb_eval(self, node->nd_iter); - ruby_current_node = node; - SET_CURRENT_SOURCE(); - result = rb_call(CLASS_OF(recv),recv,each,0,0, - block,CALLING_NORMAL,1,self); - } - else if (state == TAG_BREAK && TAG_DST()) { - result = prot_tag->retval; - state = 0; - } - else if (state == TAG_RETRY) { - state = 0; - goto for_retry; - } - POP_BLOCK(); - POP_TAG(); - if (state) JUMP_TAG(state); - } - break; - - case NODE_ITER: - { - VALUE recv = self; - calling_scope_t scope; - struct BLOCK *block_given; - - PUSH_TAG(PROT_LOOP); - PUSH_BLOCK(block_given, node->nd_var, node->nd_body); - node = node->nd_iter; /* should be NODE_CALL */ - switch (nd_type(node)) { - case NODE_CALL: - scope = CALLING_NORMAL; break; - case NODE_FCALL: - scope = CALLING_FCALL; break; - case NODE_VCALL: - scope = CALLING_VCALL; break; - case NODE_SUPER: - case NODE_ZSUPER: - scope = CALLING_SUPER; break; - default: - /* error! */ - unknown_node(node); - } - state = EXEC_TAG(); - if (state == 0) { - CALLARGS; - TMP_PROTECT; - - iter_retry: - if (scope == CALLING_NORMAL) { - recv = rb_eval(self, node->nd_recv); - } - if (nd_type(node) == NODE_ZSUPER) { - ZSUPER_ARGS(); - } - else { - SETUP_ARGS(node->nd_args); - ruby_current_node = node; - } - SET_CURRENT_SOURCE(); - switch (scope) { - case CALLING_SUPER: - result = call_super(argc, argv, block_given); - break; - default: - result = rb_call(CLASS_OF(recv),recv,node->nd_mid, - argc,argv,block_given,scope,1,self); - break; - } - } - else if (state == TAG_BREAK && TAG_DST()) { - result = prot_tag->retval; - state = 0; - } - else if (state == TAG_RETRY) { - state = 0; - goto iter_retry; - } - POP_BLOCK(); - POP_TAG(); - if (state) JUMP_TAG(state); - } - break; - - case NODE_CALL: - { - VALUE recv; - CALLARGS; - TMP_PROTECT; - - recv = rb_eval(self, node->nd_recv); - SETUP_ARGS(node->nd_args); - - ruby_current_node = node; - SET_CURRENT_SOURCE(); - result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv, - block,CALLING_NORMAL,0,self); - } - break; - - case NODE_FCALL: - { - CALLARGS; - TMP_PROTECT; - - SETUP_ARGS(node->nd_args); - - ruby_current_node = node; - SET_CURRENT_SOURCE(); - result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv, - block,CALLING_FCALL,0,self); - } - break; - - case NODE_VCALL: - SET_CURRENT_SOURCE(); - result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,0,CALLING_VCALL,0,self); - break; - - case NODE_SUPER: - case NODE_ZSUPER: - { - CALLARGS; - TMP_PROTECT; - - if (ruby_frame->this_class == 0) { - if (ruby_frame->this_func) { - rb_name_error(ruby_frame->callee, - "superclass method `%s' disabled", - rb_id2name(ruby_frame->this_func)); - } - else { - rb_raise(rb_eNoMethodError, "super called outside of method"); - } - } - if (nd_type(node) == NODE_ZSUPER) { - ZSUPER_ARGS(); - SET_CURRENT_SOURCE(); - result = rb_call_super(argc, argv); - } - else { - SETUP_ARGS(node->nd_args); - ruby_current_node = node; - SET_CURRENT_SOURCE(); - result = call_super(argc, argv, block); - } - } - break; - - case NODE_SCOPE: - { - struct FRAME frame; - NODE *saved_cref = 0; - - frame = *ruby_frame; - frame.tmp = ruby_frame; - ruby_frame = &frame; - - PUSH_SCOPE(); - PUSH_TAG(PROT_NONE); - if (node->nd_rval) { - saved_cref = ruby_cref; - ruby_cref = (NODE*)node->nd_rval; - } - if (node->nd_tbl) { - VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1); - *vars++ = (VALUE)node; - ruby_scope->local_vars = vars; - rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]); - ruby_scope->local_tbl = node->nd_tbl; - } - else { - ruby_scope->local_vars = 0; - ruby_scope->local_tbl = 0; - } - if ((state = EXEC_TAG()) == 0) { - result = rb_eval(self, node->nd_next); - } - POP_TAG(); - POP_SCOPE(); - ruby_frame = frame.tmp; - if (saved_cref) - ruby_cref = saved_cref; - if (state) JUMP_TAG(state); - } - break; - - case NODE_OP_ASGN1: - { - CALLARGS; - VALUE recv, val, tmp; - NODE *rval; - TMP_PROTECT; - - recv = rb_eval(self, node->nd_recv); - rval = node->nd_args->nd_head; - SETUP_ARGS0(node->nd_args->nd_body,1); - val = rb_funcall3(recv, aref, argc, argv); - switch (node->nd_mid) { - case 0: /* OR */ - if (RTEST(val)) RETURN(val); - val = rb_eval(self, rval); - break; - case 1: /* AND */ - if (!RTEST(val)) RETURN(val); - val = rb_eval(self, rval); - break; - default: - tmp = rb_eval(self, rval); - val = rb_funcall3(val, node->nd_mid, 1, &tmp); - } - argv[argc] = val; - rb_funcall3(recv, aset, argc+1, argv); - result = val; - } - break; - - case NODE_OP_ASGN2: - { - ID id = node->nd_next->nd_vid; - VALUE recv, val, tmp; - - recv = rb_eval(self, node->nd_recv); - val = rb_funcall3(recv, id, 0, 0); - switch (node->nd_next->nd_mid) { - case 0: /* OR */ - if (RTEST(val)) RETURN(val); - val = rb_eval(self, node->nd_value); - break; - case 1: /* AND */ - if (!RTEST(val)) RETURN(val); - val = rb_eval(self, node->nd_value); - break; - default: - tmp = rb_eval(self, node->nd_value); - val = rb_funcall3(val, node->nd_next->nd_mid, 1, &tmp); - } - - rb_funcall3(recv, node->nd_next->nd_aid, 1, &val); - result = val; - } - break; - - case NODE_OP_ASGN_AND: - result = rb_eval(self, node->nd_head); - if (!RTEST(result)) break; - node = node->nd_value; - goto again; - - case NODE_OP_ASGN_OR: - if ((node->nd_aid && !is_defined(self, node->nd_head, 0, 0)) || - !RTEST(result = rb_eval(self, node->nd_head))) { - node = node->nd_value; - goto again; - } - break; - - case NODE_MASGN: - result = massign(self, node, rb_eval(self, node->nd_value), 0); - break; - - case NODE_LASGN: - if (ruby_scope->local_vars == 0) - rb_bug("unexpected local variable assignment"); - result = rb_eval(self, node->nd_value); - ruby_scope->local_vars[node->nd_cnt] = result; - break; - - case NODE_DASGN: - result = rb_eval(self, node->nd_value); - dvar_asgn(node->nd_vid, result); - break; - - case NODE_DASGN_CURR: - result = rb_eval(self, node->nd_value); - dvar_asgn_curr(node->nd_vid, result); - break; - - case NODE_GASGN: - result = rb_eval(self, node->nd_value); - rb_gvar_set(node->nd_entry, result); - break; - - case NODE_IASGN: - result = rb_eval(self, node->nd_value); - rb_ivar_set(self, node->nd_vid, result); - break; - - case NODE_CDECL: - result = rb_eval(self, node->nd_value); - if (node->nd_vid == 0) { - rb_const_set(class_prefix(self, node->nd_else), node->nd_else->nd_mid, result); - } - else { - rb_const_set(ruby_cbase, node->nd_vid, result); - } - break; - - case NODE_CVDECL: - if (NIL_P(ruby_cbase)) { - rb_raise(rb_eTypeError, "no class/module to define class variable"); - } - result = rb_eval(self, node->nd_value); - rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qtrue); - break; - - case NODE_CVASGN: - result = rb_eval(self, node->nd_value); - rb_cvar_set(cvar_cbase(), node->nd_vid, result, Qfalse); - break; - - case NODE_LVAR: - if (ruby_scope->local_vars == 0) { - rb_bug("unexpected local variable"); - } - result = ruby_scope->local_vars[node->nd_cnt]; - break; - - case NODE_DVAR: - result = rb_dvar_ref(node->nd_vid); - break; - - case NODE_GVAR: - result = rb_gvar_get(node->nd_entry); - break; - - case NODE_IVAR: - result = rb_ivar_get(self, node->nd_vid); - break; - - case NODE_CONST: - result = ev_const_get(node->nd_vid, self); - break; - - case NODE_CVAR: - result = rb_cvar_get(cvar_cbase(), node->nd_vid); - break; - - case NODE_BLOCK_ARG: - if (ruby_scope->local_vars == 0) - rb_bug("unexpected block argument"); - if (rb_block_given_p()) { - result = rb_block_proc(); - ruby_scope->local_vars[node->nd_cnt] = result; - } - else { - result = Qnil; - } - break; - - case NODE_COLON2: - { - VALUE klass; - - klass = rb_eval(self, node->nd_head); - if (rb_is_const_id(node->nd_mid)) { - switch (TYPE(klass)) { - case T_CLASS: - case T_MODULE: - result = rb_const_get_from(klass, node->nd_mid); - break; - default: - rb_raise(rb_eTypeError, "%s is not a class/module", - RSTRING_PTR(rb_obj_as_string(klass))); - break; - } - } - else { - result = rb_funcall(klass, node->nd_mid, 0, 0); - } - } - break; - - case NODE_COLON3: - result = rb_const_get_from(rb_cObject, node->nd_mid); - break; - - case NODE_NTH_REF: - result = rb_reg_nth_match(node->nd_nth, MATCH_DATA); - break; - - case NODE_BACK_REF: - switch (node->nd_nth) { - case '&': - result = rb_reg_last_match(MATCH_DATA); - break; - case '`': - result = rb_reg_match_pre(MATCH_DATA); - break; - case '\'': - result = rb_reg_match_post(MATCH_DATA); - break; - case '+': - result = rb_reg_match_last(MATCH_DATA); - break; - default: - rb_bug("unexpected back-ref"); - } - break; - - case NODE_HASH: - { - NODE *list; - VALUE hash = rb_hash_new(); - VALUE key, val; - - list = node->nd_head; - while (list) { - key = rb_eval(self, list->nd_head); - list = list->nd_next; - if (list == 0) - rb_bug("odd number list for Hash"); - val = rb_eval(self, list->nd_head); - list = list->nd_next; - rb_hash_aset(hash, key, val); - } - result = hash; - } - break; - - case NODE_ZARRAY: /* zero length list */ - result = rb_ary_new(); - break; - - case NODE_ARRAY: - { - VALUE ary; - long i; - - i = node->nd_alen; - ary = rb_ary_new2(i); - for (i=0;node;node=node->nd_next) { - rb_ary_push(ary, rb_eval(self, node->nd_head)); - } - - result = ary; - } - break; - - case NODE_VALUES: - { - VALUE val; - long i; - - i = node->nd_alen; - val = rb_ary_new2(i); - for (i=0;node;node=node->nd_next) { - rb_ary_push(val, rb_eval(self, node->nd_head)); - } - - result = val; - } - break; - - case NODE_STR: - result = rb_str_new3(node->nd_lit); - break; - - case NODE_EVSTR: - if (!node->nd_body) result = rb_str_new(0,0); - else { - result = rb_obj_as_string(rb_eval(self, node->nd_body)); - } - break; - - case NODE_DSTR: - case NODE_DXSTR: - case NODE_DREGX: - case NODE_DREGX_ONCE: - case NODE_DSYM: - { - VALUE str, str2; - NODE *list = node->nd_next; - - str = rb_str_new3(node->nd_lit); - while (list) { - if (list->nd_head) { - switch (nd_type(list->nd_head)) { - case NODE_STR: - str2 = list->nd_head->nd_lit; - break; - default: - str2 = rb_eval(self, list->nd_head); - break; - } - rb_str_append(str, str2); - OBJ_INFECT(str, str2); - } - list = list->nd_next; - } - switch (nd_type(node)) { - case NODE_DREGX: - result = rb_reg_new(RSTRING_PTR(str), RSTRING_LEN(str), - node->nd_cflag); - break; - case NODE_DREGX_ONCE: /* regexp expand once */ - result = rb_reg_new(RSTRING_PTR(str), RSTRING_LEN(str), - node->nd_cflag); - nd_set_type(node, NODE_LIT); - node->nd_lit = result; - break; - case NODE_LIT: - /* other thread may replace NODE_DREGX_ONCE to NODE_LIT */ - goto again; - case NODE_DXSTR: - result = rb_funcall(self, '`', 1, str); - break; - case NODE_DSYM: - result = rb_str_intern(str); - break; - default: - result = str; - break; - } - } - break; - - case NODE_XSTR: - result = rb_funcall(self, '`', 1, rb_str_new3(node->nd_lit)); - break; - - case NODE_LIT: - result = node->nd_lit; - break; - - case NODE_DEFN: - if (node->nd_defn) { - NODE *body, *defn; - VALUE origin; - int noex; - - if (NIL_P(ruby_cbase)) { - rb_raise(rb_eTypeError, "no class/module to define method"); - } - if (ruby_cbase == rb_cObject && node->nd_mid == init) { - rb_warn("redefining Object#initialize may cause infinite loop"); - } - if (node->nd_mid == object_id || - node->nd_mid == __send || node->nd_mid == __send_bang) { - rb_warn("redefining `%s' may cause serious problem", - rb_id2name(node->nd_mid)); - } - rb_frozen_class_p(ruby_cbase); - body = search_method(ruby_cbase, node->nd_mid, &origin, LOOKUP_NOSKIP, 0); - if (body){ - if (RTEST(ruby_verbose) && ruby_cbase == origin && - body->nd_cnt == 0 && body->nd_body) { - rb_warning("method redefined; discarding old %s", rb_id2name(node->nd_mid)); - } - } - - if (VIS_TEST(VIS_PRIVATE) || node->nd_mid == init) { - noex = NOEX_PRIVATE; - } - else if (VIS_TEST(VIS_LOCAL)) { - noex = NOEX_LOCAL; - } - else if (VIS_TEST(VIS_PROTECTED)) { - noex = NOEX_PROTECTED; - } - else { - noex = NOEX_PUBLIC; - } - if (body && origin == ruby_cbase && body->nd_body == 0) { - noex |= NOEX_NOSUPER; - } - - defn = copy_node_scope(node->nd_defn, ruby_cref); - rb_add_method(ruby_cbase, node->nd_mid, defn, noex); - if (VIS_MODE() == VIS_MODFUNC) { - rb_add_method(rb_singleton_class(ruby_cbase), - node->nd_mid, defn, NOEX_PUBLIC); - } - result = Qnil; - } - break; - - case NODE_DEFS: - if (node->nd_defn) { - VALUE recv = rb_eval(self, node->nd_recv); - VALUE klass; - NODE *body = 0, *defn; - - if (ruby_safe_level >= 4 && !OBJ_TAINTED(recv)) { - rb_raise(rb_eSecurityError, "Insecure: can't define singleton method"); - } - if (FIXNUM_P(recv) || SYMBOL_P(recv)) { - rb_raise(rb_eTypeError, - "can't define singleton method \"%s\" for %s", - rb_id2name(node->nd_mid), - rb_obj_classname(recv)); - } - - if (OBJ_FROZEN(recv)) rb_error_frozen("object"); - klass = rb_singleton_class(recv); - if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, (st_data_t *)&body)) { - if (ruby_safe_level >= 4) { - rb_raise(rb_eSecurityError, "redefining method prohibited"); - } - if (RTEST(ruby_verbose)) { - rb_warning("redefine %s", rb_id2name(node->nd_mid)); - } - } - defn = copy_node_scope(node->nd_defn, ruby_cref); - rb_add_method(klass, node->nd_mid, defn, - NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0)); - result = Qnil; - } - break; - - case NODE_UNDEF: - if (NIL_P(ruby_cbase)) { - rb_raise(rb_eTypeError, "no class to undef method"); - } - rb_undef(ruby_cbase, rb_to_id(rb_eval(self, node->u2.node))); - result = Qnil; - break; - - case NODE_ALIAS: - if (NIL_P(ruby_cbase)) { - rb_raise(rb_eTypeError, "no class to make alias"); - } - rb_alias(ruby_cbase, rb_to_id(rb_eval(self, node->u1.node)), - rb_to_id(rb_eval(self, node->u2.node))); - result = Qnil; - break; - - case NODE_VALIAS: - rb_alias_variable(node->u1.id, node->u2.id); - result = Qnil; - break; - - case NODE_CLASS: - { - VALUE super, klass, tmp, cbase; - ID cname; - int gen = Qfalse; - - cbase = class_prefix(self, node->nd_cpath); - cname = node->nd_cpath->nd_mid; - - if (NIL_P(ruby_cbase)) { - rb_raise(rb_eTypeError, "no outer class/module"); - } - if (node->nd_super) { - super = rb_eval(self, node->nd_super); - rb_check_inheritable(super); - } - else { - super = 0; - } - - if (rb_const_defined_at(cbase, cname)) { - klass = rb_const_get_at(cbase, cname); - if (TYPE(klass) != T_CLASS) { - rb_raise(rb_eTypeError, "%s is not a class", - rb_id2name(cname)); - } - if (super) { - tmp = rb_class_real(RCLASS(klass)->super); - if (tmp != super) { - rb_raise(rb_eTypeError, "superclass mismatch for class %s", - rb_id2name(cname)); - } - super = 0; - } - if (ruby_safe_level >= 4) { - rb_raise(rb_eSecurityError, "extending class prohibited"); - } - } - else { - if (!super) super = rb_cObject; - klass = rb_define_class_id(cname, super); - rb_set_class_path(klass, cbase, rb_id2name(cname)); - rb_const_set(cbase, cname, klass); - gen = Qtrue; - } - if (ruby_wrapper) { - rb_extend_object(klass, ruby_wrapper); - rb_include_module(klass, ruby_wrapper); - } - if (super && gen) { - rb_class_inherited(super, klass); - } - result = module_setup(klass, node); - } - break; - - case NODE_MODULE: - { - VALUE module, cbase; - ID cname; - - if (NIL_P(ruby_cbase)) { - rb_raise(rb_eTypeError, "no outer class/module"); - } - cbase = class_prefix(self, node->nd_cpath); - cname = node->nd_cpath->nd_mid; - if (rb_const_defined_at(cbase, cname)) { - module = rb_const_get_at(cbase, cname); - if (TYPE(module) != T_MODULE) { - rb_raise(rb_eTypeError, "%s is not a module", - rb_id2name(cname)); - } - if (ruby_safe_level >= 4) { - rb_raise(rb_eSecurityError, "extending module prohibited"); - } - } - else { - module = rb_define_module_id(cname); - rb_set_class_path(module, cbase, rb_id2name(cname)); - rb_const_set(cbase, cname, module); - rb_obj_call_init(module, 0, 0); - } - if (ruby_wrapper) { - rb_extend_object(module, ruby_wrapper); - rb_include_module(module, ruby_wrapper); - } - result = module_setup(module, node); - } - break; - - case NODE_SCLASS: - { - VALUE klass; - - result = rb_eval(self, node->nd_recv); - if (FIXNUM_P(result) || SYMBOL_P(result)) { - rb_raise(rb_eTypeError, "no singleton class for %s", - rb_obj_classname(result)); - } - if (ruby_safe_level >= 4 && !OBJ_TAINTED(result)) - rb_raise(rb_eSecurityError, "Insecure: can't extend object"); - klass = rb_singleton_class(result); - - if (ruby_wrapper) { - rb_extend_object(klass, ruby_wrapper); - rb_include_module(klass, ruby_wrapper); - } - - result = module_setup(klass, node); - } - break; - - case NODE_DEFINED: - { - char buf[20]; - const char *desc = is_defined(self, node->nd_head, buf, 0); - - if (desc) result = rb_str_new2(desc); - else result = Qnil; - } - break; - - default: - unknown_node(node); - } - finish: - CHECK_INTS; - if (contnode) { - node = contnode; - contnode = 0; - goto again; - } - return result; + if (state) + JUMP_TAG(state); +#endif } -static VALUE -module_setup(VALUE module, NODE *n) -{ - NODE * volatile node = n->nd_body; - int state; - struct FRAME frame; - VALUE result = Qnil; /* OK */ - TMP_PROTECT; - - frame = *ruby_frame; - frame.tmp = ruby_frame; - ruby_frame = &frame; - - PUSH_SCOPE(); - PUSH_VARS(); - - if (node->nd_tbl) { - VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1); - *vars++ = (VALUE)node; - ruby_scope->local_vars = vars; - rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]); - ruby_scope->local_tbl = node->nd_tbl; - } - else { - ruby_scope->local_vars = 0; - ruby_scope->local_tbl = 0; - } - - PUSH_CREF(module); - VIS_SET(VIS_PUBLIC); - PUSH_TAG(PROT_NONE); - if ((state = EXEC_TAG()) == 0) { - EXEC_EVENT_HOOK(RUBY_EVENT_CLASS, n, ruby_cbase, - ruby_frame->this_func, ruby_frame->this_class); - result = rb_eval(ruby_cbase, node->nd_next); - } - POP_TAG(); - POP_CREF(); - POP_VARS(); - POP_SCOPE(); - ruby_frame = frame.tmp; - EXEC_EVENT_HOOK(RUBY_EVENT_END, n, 0, ruby_frame->this_func, - ruby_frame->this_class); - if (state) JUMP_TAG(state); - - return result; -} +/* + * call-seq: + * obj.respond_to?(symbol, include_private=false) => true or false + * + * Returns +true+> if _obj_ responds to the given + * method. Private methods are included in the search only if the + * optional second parameter evaluates to +true+. + */ static NODE *basic_respond_to = 0; @@ -4040,7 +699,8 @@ rb_obj_respond_to(VALUE obj, ID id, int priv) VALUE args[2]; int n = 0; args[n++] = ID2SYM(id); - if (priv) args[n++] = Qtrue; + if (priv) + args[n++] = Qtrue; return rb_funcall2(obj, respond_to, n, args); } } @@ -4076,12 +736,11 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) /* * call-seq: - * mod.method_defined?(symbol, inherit=true) => true or false + * mod.method_defined?(symbol) => true or false * * Returns +true+ if the named method is defined by * _mod_ (or its included modules and, if _mod_ is a class, - * its ancestors, if _inherit_ is true). Public and protected - * methods are matched. + * its ancestors). Public and protected methods are matched. * * module A * def method1() end @@ -4099,27 +758,13 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) * C.method_defined? "method2" #=> true * C.method_defined? "method3" #=> true * C.method_defined? "method4" #=> false - * C.method_defined?("method2", false) #=> false */ static VALUE -rb_mod_method_defined(int argc, VALUE *argv, VALUE mod) +rb_mod_method_defined(mod, mid) + VALUE mod, mid; { - VALUE mid, recur; - ID id; - - if (argc == 1) { - recur = Qtrue; - mid = argv[0]; - } - else { - rb_scan_args(argc, argv, "11", &mid, &recur); - } - id = rb_to_id(mid); - if (!RTEST(recur)) { - return st_is_member(RCLASS(mod)->m_tbl, id) ? Qtrue : Qfalse; - } - return rb_method_boundp(mod, id, Qtrue); + return rb_method_boundp(mod, rb_to_id(mid), 1); } #define VISI_CHECK(x,f) (((x)&NOEX_MASK) == (f)) @@ -4154,10 +799,11 @@ static VALUE rb_mod_public_method_defined(VALUE mod, VALUE mid) { ID id = rb_to_id(mid); - int noex = LOOKUP_NOSKIP; + NODE *method; - if (rb_get_method_body(&mod, &id, &noex)) { - if (VISI_CHECK(noex, NOEX_PUBLIC)) + method = rb_method_node(mod, id); + if (method) { + if (VISI_CHECK(method->nd_noex, NOEX_PUBLIC)) return Qtrue; } return Qfalse; @@ -4193,10 +839,11 @@ static VALUE rb_mod_private_method_defined(VALUE mod, VALUE mid) { ID id = rb_to_id(mid); - int noex = LOOKUP_NOSKIP; + NODE *method; - if (rb_get_method_body(&mod, &id, &noex)) { - if (VISI_CHECK(noex, NOEX_PRIVATE)) + method = rb_method_node(mod, id); + if (method) { + if (VISI_CHECK(method->nd_noex, NOEX_PRIVATE)) return Qtrue; } return Qfalse; @@ -42 |