mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* Merge YARV
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11439 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									3e7566d8fb
								
							
						
					
					
						commit
						a3e1b1ce7e
					
				
					 233 changed files with 46004 additions and 13653 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>
 | 
					Sun Dec 31 16:22:48 2006  Eric Hodel  <drbrain@segment7.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	* array.c: Fix Array#reject.
 | 
						* array.c: Fix Array#reject.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										69
									
								
								array.c
									
										
									
									
									
								
							
							
						
						
									
										69
									
								
								array.c
									
										
									
									
									
								
							| 
						 | 
					@ -44,7 +44,7 @@ static void
 | 
				
			||||||
ary_iter_check(VALUE ary)
 | 
					ary_iter_check(VALUE ary)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (FL_TEST(ary, ARY_ITERLOCK)) {
 | 
					    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
 | 
					#define ARY_SORTLOCK FL_USER3
 | 
				
			||||||
| 
						 | 
					@ -143,7 +143,7 @@ ary_new(VALUE klass, long len)
 | 
				
			||||||
	rb_raise(rb_eArgError, "array size too big");
 | 
						rb_raise(rb_eArgError, "array size too big");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ary = ary_alloc(klass);
 | 
					    ary = ary_alloc(klass);
 | 
				
			||||||
    if (len == 0) len++;
 | 
						if (len == 0) len++;
 | 
				
			||||||
    RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
 | 
					    RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
 | 
				
			||||||
    RARRAY(ary)->aux.capa = 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");
 | 
					    return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static VALUE rb_ary_replace(VALUE, VALUE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  call-seq:
 | 
					 *  call-seq:
 | 
				
			||||||
 *     Array.new(size=0, obj=nil)
 | 
					 *     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_raise(rb_eArgError, "array size too big");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rb_ary_modify(ary);
 | 
					    rb_ary_modify(ary);
 | 
				
			||||||
    RESIZE_CAPA(ary, len);
 | 
						RESIZE_CAPA(ary, len);
 | 
				
			||||||
    if (rb_block_given_p()) {
 | 
					    if (rb_block_given_p()) {
 | 
				
			||||||
	long i;
 | 
						long i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -543,10 +541,10 @@ rb_ary_shift(VALUE ary)
 | 
				
			||||||
    top = RARRAY_PTR(ary)[0];
 | 
					    top = RARRAY_PTR(ary)[0];
 | 
				
			||||||
    if (!ARY_SHARED_P(ary)) {
 | 
					    if (!ARY_SHARED_P(ary)) {
 | 
				
			||||||
	if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
 | 
						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--;
 | 
						    RARRAY(ary)->len--;
 | 
				
			||||||
	    return top;
 | 
						return top;
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	RARRAY_PTR(ary)[0] = Qnil;
 | 
						RARRAY_PTR(ary)[0] = Qnil;
 | 
				
			||||||
	ary_make_shared(ary);
 | 
						ary_make_shared(ary);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -590,7 +588,7 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
 | 
				
			||||||
    if (ARY_SHARED_P(ary)) {
 | 
					    if (ARY_SHARED_P(ary)) {
 | 
				
			||||||
	RARRAY(ary)->ptr += n;
 | 
						RARRAY(ary)->ptr += n;
 | 
				
			||||||
	RARRAY(ary)->len -= n;
 | 
						RARRAY(ary)->len -= n;
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
	MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
 | 
						MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
 | 
				
			||||||
	RARRAY(ary)->len -= 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);
 | 
					    if (len == 0) return ary_new(klass, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shared = ary_make_shared(ary);
 | 
					    shared = ary_make_shared(ary);
 | 
				
			||||||
    ptr = RARRAY_PTR(ary);
 | 
						ptr = RARRAY_PTR(ary);
 | 
				
			||||||
    ary2 = ary_alloc(klass);
 | 
					    ary2 = ary_alloc(klass);
 | 
				
			||||||
    RARRAY(ary2)->ptr = ptr + beg;
 | 
					    RARRAY(ary2)->ptr = ptr + beg;
 | 
				
			||||||
    RARRAY(ary2)->len = len;
 | 
					    RARRAY(ary2)->len = len;
 | 
				
			||||||
| 
						 | 
					@ -775,8 +773,8 @@ rb_ary_at(VALUE ary, VALUE pos)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  call-seq:
 | 
					 *  call-seq:
 | 
				
			||||||
 *     array.first     ->   obj or nil
 | 
					 *     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.
 | 
					 *  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
 | 
					 *  If the array is empty, the first form returns <code>nil</code>, and the
 | 
				
			||||||
 *  second form returns an empty array.
 | 
					 *  second form returns an empty array.
 | 
				
			||||||
| 
						 | 
					@ -931,7 +929,7 @@ rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
 | 
				
			||||||
    long i = RARRAY_LEN(ary);
 | 
					    long i = RARRAY_LEN(ary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (rb_scan_args(argc, argv, "01", &val) == 0) {
 | 
					    if (rb_scan_args(argc, argv, "01", &val) == 0) {
 | 
				
			||||||
	RETURN_ENUMERATOR(ary, 0, 0);
 | 
						    RETURN_ENUMERATOR(ary, 0, 0);
 | 
				
			||||||
	while (i--) {
 | 
						while (i--) {
 | 
				
			||||||
	    if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
 | 
						    if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
 | 
				
			||||||
		return LONG2NUM(i);
 | 
							return LONG2NUM(i);
 | 
				
			||||||
| 
						 | 
					@ -1145,11 +1143,23 @@ each_i(VALUE ary)
 | 
				
			||||||
 *     a -- b -- c --
 | 
					 *     a -- b -- c --
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE yarv_invoke_Array_each_special_block(VALUE ary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VALUE
 | 
					VALUE
 | 
				
			||||||
rb_ary_each(VALUE ary)
 | 
					rb_ary_each(VALUE ary)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    long i;
 | 
				
			||||||
 | 
					    VALUE val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RETURN_ENUMERATOR(ary, 0, 0);
 | 
					    RETURN_ENUMERATOR(ary, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val = yarv_invoke_Array_each_special_block(ary);
 | 
				
			||||||
 | 
					    if(val != Qundef){
 | 
				
			||||||
 | 
						return val;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ITERATE(each_i, ary);
 | 
					    ITERATE(each_i, ary);
 | 
				
			||||||
 | 
					    return ary;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static VALUE
 | 
					static VALUE
 | 
				
			||||||
| 
						 | 
					@ -1158,7 +1168,7 @@ each_index_i(VALUE ary)
 | 
				
			||||||
    long i;
 | 
					    long i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i=0; i<RARRAY_LEN(ary); i++) {
 | 
					    for (i=0; i<RARRAY_LEN(ary); i++) {
 | 
				
			||||||
	rb_yield(LONG2NUM(i));
 | 
					      rb_yield(LONG2NUM(i));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return ary;
 | 
					    return ary;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1530,7 +1540,7 @@ sort_i(VALUE ary)
 | 
				
			||||||
    data.ary = ary;
 | 
					    data.ary = ary;
 | 
				
			||||||
    data.ptr = RARRAY_PTR(ary); data.len = RARRAY_LEN(ary);
 | 
					    data.ptr = RARRAY_PTR(ary); data.len = RARRAY_LEN(ary);
 | 
				
			||||||
    ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE),
 | 
					    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;
 | 
					    return ary;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1890,7 +1900,6 @@ rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
 | 
				
			||||||
    return rb_ary_delete_at(ary, NUM2LONG(arg1));
 | 
					    return rb_ary_delete_at(ary, NUM2LONG(arg1));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static VALUE
 | 
					static VALUE
 | 
				
			||||||
reject_bang_i(VALUE ary)
 | 
					reject_bang_i(VALUE ary)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1905,10 +1914,10 @@ reject_bang_i(VALUE ary)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	i2++;
 | 
						i2++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (RARRAY_LEN(ary) == i2) return Qnil;
 | 
					    if (RARRAY_LEN(ary) == i2) return Qnil;
 | 
				
			||||||
    if (i2 < RARRAY_LEN(ary))
 | 
					    if (i2 < RARRAY_LEN(ary))
 | 
				
			||||||
	RARRAY(ary)->len = i2;
 | 
						RARRAY(ary)->len = i2;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ary;
 | 
					    return ary;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2075,7 +2084,7 @@ rb_ary_transpose(VALUE ary)
 | 
				
			||||||
 *     a                              #=> ["x", "y", "z"]
 | 
					 *     a                              #=> ["x", "y", "z"]
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static VALUE
 | 
					VALUE
 | 
				
			||||||
rb_ary_replace(VALUE copy, VALUE orig)
 | 
					rb_ary_replace(VALUE copy, VALUE orig)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VALUE shared;
 | 
					    VALUE shared;
 | 
				
			||||||
| 
						 | 
					@ -2087,7 +2096,7 @@ rb_ary_replace(VALUE copy, VALUE orig)
 | 
				
			||||||
    if (copy == orig) return copy;
 | 
					    if (copy == orig) return copy;
 | 
				
			||||||
    shared = ary_make_shared(orig);
 | 
					    shared = ary_make_shared(orig);
 | 
				
			||||||
    ptr = RARRAY(copy)->ptr;
 | 
					    ptr = RARRAY(copy)->ptr;
 | 
				
			||||||
    xfree(ptr);
 | 
						xfree(ptr);
 | 
				
			||||||
    RARRAY(copy)->ptr = RARRAY(shared)->ptr;
 | 
					    RARRAY(copy)->ptr = RARRAY(shared)->ptr;
 | 
				
			||||||
    RARRAY(copy)->len = RARRAY(shared)->len;
 | 
					    RARRAY(copy)->len = RARRAY(shared)->len;
 | 
				
			||||||
    RARRAY(copy)->aux.shared = shared;
 | 
					    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_push(memo, id);
 | 
				
			||||||
    rb_ary_splice(ary, idx, 1, ary2);
 | 
					    rb_ary_splice(ary, idx, 1, ary2);
 | 
				
			||||||
    if (level != 0) {
 | 
					    if (level != 0) {
 | 
				
			||||||
	while (i < lim) {
 | 
					    while (i < lim) {
 | 
				
			||||||
	    VALUE tmp;
 | 
						VALUE tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    tmp = rb_check_array_type(rb_ary_elt(ary, i));
 | 
						tmp = rb_check_array_type(rb_ary_elt(ary, i));
 | 
				
			||||||
	    if (!NIL_P(tmp)) {
 | 
						if (!NIL_P(tmp)) {
 | 
				
			||||||
		n = flatten(ary, i, tmp, memo, level);
 | 
							n = flatten(ary, i, tmp, memo, level);
 | 
				
			||||||
		i += n; lim += n;
 | 
						    i += n; lim += n;
 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    i++;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						i++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rb_ary_pop(memo);
 | 
					    rb_ary_pop(memo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2822,7 +2831,7 @@ flatten(VALUE ary, long idx, VALUE ary2, VALUE memo, int level)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  call-seq:
 | 
					 *  call-seq:
 | 
				
			||||||
 *     array.flatten!        -> array or nil
 | 
					 *     array.flatten! -> array or nil
 | 
				
			||||||
 *     array.flatten!(level) -> array or nil
 | 
					 *     array.flatten!(level) -> array or nil
 | 
				
			||||||
 *  
 | 
					 *  
 | 
				
			||||||
 *  Flattens _self_ in place.
 | 
					 *  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.
 | 
					 *  argument determins the level of recursion to flatten.
 | 
				
			||||||
 *     
 | 
					 *     
 | 
				
			||||||
 *     a = [ 1, 2, [3, [4, 5] ] ]
 | 
					 *     a = [ 1, 2, [3, [4, 5] ] ]
 | 
				
			||||||
 *     a.flatten!    #=> [1, 2, 3, 4, 5]
 | 
					 *     a.flatten!   #=> [1, 2, 3, 4, 5]
 | 
				
			||||||
 *     a.flatten!    #=> nil
 | 
					 *     a.flatten!   #=> nil
 | 
				
			||||||
 *     a             #=> [1, 2, 3, 4, 5]
 | 
					 *     a            #=> [1, 2, 3, 4, 5]
 | 
				
			||||||
 *     a = [ 1, 2, [3, [4, 5] ] ]
 | 
					 *     a = [ 1, 2, [3, [4, 5] ] ]
 | 
				
			||||||
 *     a.flatten!(1) #=> [1, 2, 3, [4, 5]]
 | 
					 *     a.flatten!(1) #=> [1, 2, 3, [4, 5]]
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								benchmark/bm_app_answer.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								benchmark/bm_app_answer.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										11
									
								
								benchmark/bm_app_factorial.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								benchmark/bm_app_factorial.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					def fact(n)
 | 
				
			||||||
 | 
					  if(n > 1)
 | 
				
			||||||
 | 
					    n * fact(n-1)
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					8.times{
 | 
				
			||||||
 | 
					  fact(5000)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								benchmark/bm_app_fib.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								benchmark/bm_app_fib.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					def fib n
 | 
				
			||||||
 | 
					  if n < 3
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    fib(n-1) + fib(n-2)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fib(34)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								benchmark/bm_app_mandelbrot.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								benchmark/bm_app_mandelbrot.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										259
									
								
								benchmark/bm_app_pentomino.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								benchmark/bm_app_pentomino.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
							
								
								
									
										8
									
								
								benchmark/bm_app_raise.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								benchmark/bm_app_raise.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<300000
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					    raise
 | 
				
			||||||
 | 
					  rescue
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										5
									
								
								benchmark/bm_app_strconcat.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								benchmark/bm_app_strconcat.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<500000
 | 
				
			||||||
 | 
					  "#{1+1} #{1+1} #{1+1}"
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										13
									
								
								benchmark/bm_app_tak.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								benchmark/bm_app_tak.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								benchmark/bm_app_tarai.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								benchmark/bm_app_tarai.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
							
								
								
									
										1
									
								
								benchmark/bm_loop_times.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								benchmark/bm_loop_times.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					30000000.times{|e|}
 | 
				
			||||||
							
								
								
									
										4
									
								
								benchmark/bm_loop_whileloop.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								benchmark/bm_loop_whileloop.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					i = 0
 | 
				
			||||||
 | 
					while i<30000000 # benchmark loop 1
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										5
									
								
								benchmark/bm_loop_whileloop2.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								benchmark/bm_loop_whileloop2.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<6000000 # benchmark loop 2
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								benchmark/bm_so_ackermann.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								benchmark/bm_so_ackermann.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								benchmark/bm_so_array.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								benchmark/bm_so_array.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								benchmark/bm_so_concatenate.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								benchmark/bm_so_concatenate.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								benchmark/bm_so_count_words.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								benchmark/bm_so_count_words.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								benchmark/bm_so_exception.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								benchmark/bm_so_exception.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										47
									
								
								benchmark/bm_so_lists.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								benchmark/bm_so_lists.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										48
									
								
								benchmark/bm_so_matrix.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								benchmark/bm_so_matrix.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										24
									
								
								benchmark/bm_so_nested_loop.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								benchmark/bm_so_nested_loop.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										56
									
								
								benchmark/bm_so_object.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								benchmark/bm_so_object.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								benchmark/bm_so_random.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								benchmark/bm_so_random.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
							
								
								
									
										24
									
								
								benchmark/bm_so_sieve.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								benchmark/bm_so_sieve.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										10
									
								
								benchmark/bm_vm1_block.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								benchmark/bm_vm1_block.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					def m
 | 
				
			||||||
 | 
					  yield
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<30000000 # while loop 1
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  m{
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										8
									
								
								benchmark/bm_vm1_const.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								benchmark/bm_vm1_const.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					Const = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i = 0
 | 
				
			||||||
 | 
					while i<30000000 # while loop 1
 | 
				
			||||||
 | 
					  i+= 1
 | 
				
			||||||
 | 
					  j = Const
 | 
				
			||||||
 | 
					  k = Const
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										11
									
								
								benchmark/bm_vm1_ensure.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								benchmark/bm_vm1_ensure.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<30000000 # benchmark loop 1
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					    begin
 | 
				
			||||||
 | 
					    ensure
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  ensure
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										9
									
								
								benchmark/bm_vm1_length.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								benchmark/bm_vm1_length.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								benchmark/bm_vm1_rescue.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								benchmark/bm_vm1_rescue.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<30000000 # while loop 1
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  begin
 | 
				
			||||||
 | 
					  rescue
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										9
									
								
								benchmark/bm_vm1_simplereturn.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								benchmark/bm_vm1_simplereturn.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					def m
 | 
				
			||||||
 | 
					  return 1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<30000000 # while loop 1
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  m
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								benchmark/bm_vm1_swap.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								benchmark/bm_vm1_swap.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					a = 1
 | 
				
			||||||
 | 
					b = 2
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<30000000 # while loop 1
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  a, b = b, a
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										5
									
								
								benchmark/bm_vm2_array.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								benchmark/bm_vm2_array.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										9
									
								
								benchmark/bm_vm2_method.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								benchmark/bm_vm2_method.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										20
									
								
								benchmark/bm_vm2_poly_method.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								benchmark/bm_vm2_poly_method.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										20
									
								
								benchmark/bm_vm2_poly_method_ov.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								benchmark/bm_vm2_poly_method_ov.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										14
									
								
								benchmark/bm_vm2_proc.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								benchmark/bm_vm2_proc.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								benchmark/bm_vm2_regexp.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								benchmark/bm_vm2_regexp.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					str = 'xxxhogexxx'
 | 
				
			||||||
 | 
					while i<6000000 # benchmark loop 2
 | 
				
			||||||
 | 
					  /hoge/ =~ str
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										12
									
								
								benchmark/bm_vm2_send.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								benchmark/bm_vm2_send.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										20
									
								
								benchmark/bm_vm2_super.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								benchmark/bm_vm2_super.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										8
									
								
								benchmark/bm_vm2_unif1.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								benchmark/bm_vm2_unif1.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					i = 0
 | 
				
			||||||
 | 
					def m a, b
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while i<6000000 # benchmark loop 2
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  m 100, 200
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										20
									
								
								benchmark/bm_vm2_zsuper.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								benchmark/bm_vm2_zsuper.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										6
									
								
								benchmark/bm_vm3_thread_create_join.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								benchmark/bm_vm3_thread_create_join.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<1000 # benchmark loop 3
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					  Thread.new{
 | 
				
			||||||
 | 
					  }.join
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										57
									
								
								benchmark/bmx_temp.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								benchmark/bmx_temp.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								benchmark/other-lang/ack.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								benchmark/other-lang/ack.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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);
 | 
				
			||||||
							
								
								
									
										16
									
								
								benchmark/other-lang/ack.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								benchmark/other-lang/ack.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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()
 | 
				
			||||||
							
								
								
									
										12
									
								
								benchmark/other-lang/ack.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								benchmark/other-lang/ack.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
							
								
								
									
										7
									
								
								benchmark/other-lang/ack.scm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								benchmark/other-lang/ack.scm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										66
									
								
								benchmark/other-lang/eval.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								benchmark/other-lang/eval.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								benchmark/other-lang/fact.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								benchmark/other-lang/fact.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								benchmark/other-lang/fact.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								benchmark/other-lang/fact.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								benchmark/other-lang/fact.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								benchmark/other-lang/fact.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
							
								
								
									
										8
									
								
								benchmark/other-lang/fact.scm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								benchmark/other-lang/fact.scm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,8 @@
 | 
				
			||||||
 | 
					(define (fact n)
 | 
				
			||||||
 | 
					        (if (< n 2)
 | 
				
			||||||
 | 
					            1
 | 
				
			||||||
 | 
					          (* n (fact (- n 1)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(dotimes (i 10000)
 | 
				
			||||||
 | 
					  (fact 100))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								benchmark/other-lang/fib.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								benchmark/other-lang/fib.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					sub fib{
 | 
				
			||||||
 | 
					  my $n = $_[0];
 | 
				
			||||||
 | 
					  if($n < 3){
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else{
 | 
				
			||||||
 | 
					    return fib($n-1) + fib($n-2);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					&fib(34);
 | 
				
			||||||
							
								
								
									
										7
									
								
								benchmark/other-lang/fib.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								benchmark/other-lang/fib.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					def fib(n):
 | 
				
			||||||
 | 
					  if n < 3:
 | 
				
			||||||
 | 
					    return 1
 | 
				
			||||||
 | 
					  else:
 | 
				
			||||||
 | 
					    return fib(n-1) + fib(n-2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fib(34)
 | 
				
			||||||
							
								
								
									
										9
									
								
								benchmark/other-lang/fib.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								benchmark/other-lang/fib.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					def fib n
 | 
				
			||||||
 | 
					  if n < 3
 | 
				
			||||||
 | 
					    1
 | 
				
			||||||
 | 
					  else
 | 
				
			||||||
 | 
					    fib(n-1) + fib(n-2)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fib(34)
 | 
				
			||||||
							
								
								
									
										7
									
								
								benchmark/other-lang/fib.scm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								benchmark/other-lang/fib.scm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					(define (fib n)
 | 
				
			||||||
 | 
					        (if (< n 3)
 | 
				
			||||||
 | 
					            1
 | 
				
			||||||
 | 
					          (+ (fib (- n 1)) (fib (- n 2)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(fib 34)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								benchmark/other-lang/loop.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								benchmark/other-lang/loop.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					for($i=0; $i<30000000; $i++){
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								benchmark/other-lang/loop.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								benchmark/other-lang/loop.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					for i in xrange(30000000):
 | 
				
			||||||
 | 
						pass
 | 
				
			||||||
							
								
								
									
										4
									
								
								benchmark/other-lang/loop.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								benchmark/other-lang/loop.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					i=0
 | 
				
			||||||
 | 
					while i<30000000
 | 
				
			||||||
 | 
					  i+=1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										1
									
								
								benchmark/other-lang/loop.scm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								benchmark/other-lang/loop.scm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					(dotimes (x 30000000))
 | 
				
			||||||
							
								
								
									
										1
									
								
								benchmark/other-lang/loop2.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								benchmark/other-lang/loop2.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					30000000.times{}
 | 
				
			||||||
							
								
								
									
										11
									
								
								benchmark/other-lang/tak.pl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								benchmark/other-lang/tak.pl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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);
 | 
				
			||||||
							
								
								
									
										8
									
								
								benchmark/other-lang/tak.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								benchmark/other-lang/tak.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
							
								
								
									
										13
									
								
								benchmark/other-lang/tak.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								benchmark/other-lang/tak.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								benchmark/other-lang/tak.scm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								benchmark/other-lang/tak.scm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										81
									
								
								benchmark/report.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								benchmark/report.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										137
									
								
								benchmark/run.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								benchmark/run.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										129
									
								
								benchmark/run_rite.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								benchmark/run_rite.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								benchmark/runc.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								benchmark/runc.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										25
									
								
								benchmark/wc.input.base
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								benchmark/wc.input.base
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										461
									
								
								blockinlining.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										461
									
								
								blockinlining.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										94
									
								
								call_cfunc.ci
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								call_cfunc.ci
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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 */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										81
									
								
								class.c
									
										
									
									
									
								
							
							
						
						
									
										81
									
								
								class.c
									
										
									
									
									
								
							| 
						 | 
					@ -56,10 +56,26 @@ rb_class_new(VALUE super)
 | 
				
			||||||
    return rb_class_boot(super);
 | 
					    return rb_class_boot(super);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct clone_method_data {
 | 
				
			||||||
 | 
					    st_table *tbl;
 | 
				
			||||||
 | 
					    VALUE klass;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					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;
 | 
					    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);
 | 
						st_delete(RCLASS(clone)->iv_tbl, (st_data_t*)&id, 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (RCLASS(orig)->m_tbl) {
 | 
					    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_foreach(RCLASS(orig)->m_tbl, clone_method,
 | 
				
			||||||
	  (st_data_t)RCLASS(clone)->m_tbl);
 | 
						  (st_data_t)&data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return clone;
 | 
					    return clone;
 | 
				
			||||||
| 
						 | 
					@ -111,6 +129,7 @@ rb_singleton_class_clone(VALUE obj)
 | 
				
			||||||
    if (!FL_TEST(klass, FL_SINGLETON))
 | 
					    if (!FL_TEST(klass, FL_SINGLETON))
 | 
				
			||||||
	return klass;
 | 
						return klass;
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
 | 
						struct clone_method_data data;
 | 
				
			||||||
	/* copy singleton(unnamed) class */
 | 
						/* copy singleton(unnamed) class */
 | 
				
			||||||
	NEWOBJ(clone, struct RClass);
 | 
						NEWOBJ(clone, struct RClass);
 | 
				
			||||||
	OBJSETUP(clone, 0, RBASIC(klass)->flags);
 | 
						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->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	clone->m_tbl = st_init_numtable();
 | 
						clone->m_tbl = st_init_numtable();
 | 
				
			||||||
 | 
						data.tbl = clone->m_tbl;
 | 
				
			||||||
 | 
						data.klass = (VALUE)clone;
 | 
				
			||||||
	st_foreach(RCLASS(klass)->m_tbl, clone_method,
 | 
						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);
 | 
						rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
 | 
				
			||||||
	FL_SET(clone, FL_SINGLETON);
 | 
						FL_SET(clone, FL_SINGLETON);
 | 
				
			||||||
	return (VALUE)clone;
 | 
						return (VALUE)clone;
 | 
				
			||||||
| 
						 | 
					@ -359,27 +380,27 @@ rb_include_module(VALUE klass, VALUE module)
 | 
				
			||||||
    OBJ_INFECT(klass, module);
 | 
					    OBJ_INFECT(klass, module);
 | 
				
			||||||
    c = klass;
 | 
					    c = klass;
 | 
				
			||||||
    while (module) {
 | 
					    while (module) {
 | 
				
			||||||
	int superclass_seen = Qfalse;
 | 
					       int superclass_seen = Qfalse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl)
 | 
						if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl)
 | 
				
			||||||
	    rb_raise(rb_eArgError, "cyclic include detected");
 | 
						    rb_raise(rb_eArgError, "cyclic include detected");
 | 
				
			||||||
	/* ignore if the module included already in superclasses */
 | 
					       /* ignore if the module included already in superclasses */
 | 
				
			||||||
	for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
 | 
					       for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
 | 
				
			||||||
	    switch (BUILTIN_TYPE(p)) {
 | 
					           switch (BUILTIN_TYPE(p)) {
 | 
				
			||||||
	      case T_ICLASS:
 | 
					             case T_ICLASS:
 | 
				
			||||||
		if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
 | 
					               if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
 | 
				
			||||||
		    if (!superclass_seen) {
 | 
					                   if (!superclass_seen) {
 | 
				
			||||||
			c = p;	/* move insertion point */
 | 
					                       c = p;  /* move insertion point */
 | 
				
			||||||
		    }
 | 
					                   }
 | 
				
			||||||
		    goto skip;
 | 
					                   goto skip;
 | 
				
			||||||
		}
 | 
					               }
 | 
				
			||||||
		break;
 | 
					               break;
 | 
				
			||||||
	      case T_CLASS:
 | 
					             case T_CLASS:
 | 
				
			||||||
		superclass_seen = Qtrue;
 | 
					               superclass_seen = Qtrue;
 | 
				
			||||||
		break;
 | 
					               break;
 | 
				
			||||||
	    }
 | 
					           }
 | 
				
			||||||
	}
 | 
					       }
 | 
				
			||||||
	c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
 | 
					       c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
 | 
				
			||||||
	changed = 1;
 | 
						changed = 1;
 | 
				
			||||||
      skip:
 | 
					      skip:
 | 
				
			||||||
	module = RCLASS(module)->super;
 | 
						module = RCLASS(module)->super;
 | 
				
			||||||
| 
						 | 
					@ -492,6 +513,7 @@ static int
 | 
				
			||||||
ins_methods_push(ID name, long type, VALUE ary, long visi)
 | 
					ins_methods_push(ID name, long type, VALUE ary, long visi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (type == -1) return ST_CONTINUE;
 | 
					    if (type == -1) return ST_CONTINUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (visi) {
 | 
					    switch (visi) {
 | 
				
			||||||
      case NOEX_PRIVATE:
 | 
					      case NOEX_PRIVATE:
 | 
				
			||||||
      case NOEX_PROTECTED:
 | 
					      case NOEX_PROTECTED:
 | 
				
			||||||
| 
						 | 
					@ -544,10 +566,17 @@ method_entry(ID key, NODE *body, st_table *list)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    long type;
 | 
					    long type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (key == ID_ALLOCATOR) return ST_CONTINUE;
 | 
					    if (key == ID_ALLOCATOR) {
 | 
				
			||||||
 | 
						return ST_CONTINUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    if (!st_lookup(list, key, 0)) {
 | 
					    if (!st_lookup(list, key, 0)) {
 | 
				
			||||||
	if (!body->nd_body) type = -1; /* none */
 | 
						if (body ==0 || !body->nd_body->nd_body) {
 | 
				
			||||||
	else type = VISI(body->nd_noex);
 | 
						    type = -1; /* none */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
						    type = VISI(body->nd_body->nd_noex);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	st_add_direct(list, key, type);
 | 
						st_add_direct(list, key, type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return ST_CONTINUE;
 | 
					    return ST_CONTINUE;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										403
									
								
								common.mk
									
										
									
									
									
								
							
							
						
						
									
										403
									
								
								common.mk
									
										
									
									
									
								
							| 
						 | 
					@ -1,15 +1,11 @@
 | 
				
			||||||
bin: $(PROGRAM) $(WPROGRAM)
 | 
					bin: $(PROGRAM) $(WPROGRAM)
 | 
				
			||||||
lib: $(LIBRUBY)
 | 
					lib: $(LIBRUBY);
 | 
				
			||||||
dll: $(LIBRUBY_SO)
 | 
					dll: $(LIBRUBY_SO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUBYOPT       =
 | 
					RUBYOPT       =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STATIC_RUBY   = static-ruby
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXTCONF       = extconf.rb
 | 
					EXTCONF       = extconf.rb
 | 
				
			||||||
RBCONFIG      = ./.rbconfig.time
 | 
					RBCONFIG      = ./.rbconfig.time
 | 
				
			||||||
LIBRUBY_EXTS  = ./.libruby-with-ext.time
 | 
					 | 
				
			||||||
RDOCOUT       = $(EXTOUT)/rdoc
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
DMYEXT	      = dmyext.$(OBJEXT)
 | 
					DMYEXT	      = dmyext.$(OBJEXT)
 | 
				
			||||||
MAINOBJ	      = main.$(OBJEXT)
 | 
					MAINOBJ	      = main.$(OBJEXT)
 | 
				
			||||||
| 
						 | 
					@ -28,6 +24,9 @@ OBJS	      = array.$(OBJEXT) \
 | 
				
			||||||
		error.$(OBJEXT) \
 | 
							error.$(OBJEXT) \
 | 
				
			||||||
		euc_jp.$(OBJEXT) \
 | 
							euc_jp.$(OBJEXT) \
 | 
				
			||||||
		eval.$(OBJEXT) \
 | 
							eval.$(OBJEXT) \
 | 
				
			||||||
 | 
							eval_load.$(OBJEXT) \
 | 
				
			||||||
 | 
							eval_proc.$(OBJEXT) \
 | 
				
			||||||
 | 
							eval_thread.$(OBJEXT) \
 | 
				
			||||||
		file.$(OBJEXT) \
 | 
							file.$(OBJEXT) \
 | 
				
			||||||
		gc.$(OBJEXT) \
 | 
							gc.$(OBJEXT) \
 | 
				
			||||||
		hash.$(OBJEXT) \
 | 
							hash.$(OBJEXT) \
 | 
				
			||||||
| 
						 | 
					@ -61,218 +60,94 @@ OBJS	      = array.$(OBJEXT) \
 | 
				
			||||||
		util.$(OBJEXT) \
 | 
							util.$(OBJEXT) \
 | 
				
			||||||
		variable.$(OBJEXT) \
 | 
							variable.$(OBJEXT) \
 | 
				
			||||||
		version.$(OBJEXT) \
 | 
							version.$(OBJEXT) \
 | 
				
			||||||
 | 
							blockinlining.$(OBJEXT) \
 | 
				
			||||||
 | 
							compile.$(OBJEXT) \
 | 
				
			||||||
 | 
							debug.$(OBJEXT) \
 | 
				
			||||||
 | 
							iseq.$(OBJEXT) \
 | 
				
			||||||
 | 
							vm.$(OBJEXT) \
 | 
				
			||||||
 | 
							vm_dump.$(OBJEXT) \
 | 
				
			||||||
 | 
							yarvcore.$(OBJEXT) \
 | 
				
			||||||
 | 
							thread.$(OBJEXT) \
 | 
				
			||||||
		$(MISSING)
 | 
							$(MISSING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SCRIPT_ARGS   =	--dest-dir="$(DESTDIR)" \
 | 
					SCRIPT_ARGS   =	--dest-dir="$(DESTDIR)" \
 | 
				
			||||||
		--extout="$(EXTOUT)" \
 | 
					 | 
				
			||||||
		--make="$(MAKE)" \
 | 
							--make="$(MAKE)" \
 | 
				
			||||||
		--mflags="$(MFLAGS)" \
 | 
							--mflags="$(MFLAGS)" \
 | 
				
			||||||
		--make-flags="$(MAKEFLAGS)"
 | 
							--make-flags="$(MAKEFLAGS)"
 | 
				
			||||||
EXTMK_ARGS    =	$(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) --
 | 
					EXTMK_ARGS    =	$(SCRIPT_ARGS) --extout="$(EXTOUT)" --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
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
all: $(MKFILES) $(PREP) $(RBCONFIG) $(LIBRUBY)
 | 
					all: $(MKFILES) $(PREP) $(RBCONFIG) $(LIBRUBY)
 | 
				
			||||||
	@$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS)
 | 
						$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
prog: $(PROGRAM) $(WPROGRAM)
 | 
					prog: $(PROGRAM) $(WPROGRAM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT)
 | 
					miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP)
 | 
					$(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):
 | 
					static-ruby: $(MAINOBJ) $(EXTOBJS) $(LIBRUBY_A)
 | 
				
			||||||
	@exit > $@
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$(STATIC_RUBY)$(EXEEXT): $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A)
 | 
					 | 
				
			||||||
	@$(RM) $@
 | 
						@$(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)
 | 
					ruby.imp: $(LIBRUBY_A)
 | 
				
			||||||
	@$(NM) -Pgp $(OBJS) | awk 'BEGIN{print "#!"}; $$2~/^[BD]$$/{print $$1}' | sort -u -o $@
 | 
						@$(NM) -Pgp $(LIBRUBY_A) | awk 'BEGIN{print "#!"}; $$2~/^[BD]$$/{print $$1}' | sort -u -o $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install: install-nodoc $(RDOCTARGET)
 | 
					install: install-nodoc $(RDOCTARGET)
 | 
				
			||||||
install-all: install-nodoc install-doc
 | 
					install-all: install-nodoc install-doc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc
 | 
					install-nodoc: install-local install-ext
 | 
				
			||||||
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-local: pre-install-local do-install-local post-install-local
 | 
					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
 | 
					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
 | 
					do-install-local: $(RBCONFIG)
 | 
				
			||||||
pre-install-arch:: pre-install-bin pre-install-ext-arch
 | 
						$(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --mantype="$(MANTYPE)"
 | 
				
			||||||
do-install-arch:
 | 
					do-install-ext: $(RBCONFIG)
 | 
				
			||||||
	$(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=bin --install=ext-arch
 | 
						$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) install
 | 
				
			||||||
post-install-arch:: post-install-bin post-install-ext-arch
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
install-comm: pre-install-comm do-install-comm post-install-comm
 | 
					install-bin: $(RBCONFIG)
 | 
				
			||||||
pre-install-comm:: pre-install-lib pre-install-ext-comm pre-install-man
 | 
						$(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=bin
 | 
				
			||||||
do-install-comm:
 | 
					install-lib: $(RBCONFIG)
 | 
				
			||||||
	$(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man
 | 
						$(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=lib
 | 
				
			||||||
post-install-comm:: post-install-lib post-install-ext-comm post-install-man
 | 
					install-man: $(RBCONFIG)
 | 
				
			||||||
 | 
						$(MINIRUBY) $(srcdir)/instruby.rb $(SCRIPT_ARGS) --install=man --mantype="$(MANTYPE)"
 | 
				
			||||||
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-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
 | 
					what-where-local: no-install-local
 | 
				
			||||||
no-install-local: pre-no-install-local dont-install-local post-no-install-local
 | 
					no-install-local: $(RBCONFIG)
 | 
				
			||||||
pre-no-install-local:: pre-no-install-bin pre-no-install-lib pre-no-install-man
 | 
						$(MINIRUBY) $(srcdir)/instruby.rb -n $(SCRIPT_ARGS) --mantype="$(MANTYPE)"
 | 
				
			||||||
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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
what-where-ext: no-install-ext
 | 
					what-where-ext: no-install-ext
 | 
				
			||||||
no-install-ext: pre-no-install-ext dont-install-ext post-no-install-ext
 | 
					no-install-ext: $(RBCONFIG)
 | 
				
			||||||
pre-no-install-ext:: pre-no-install-ext-arch pre-no-install-ext-comm
 | 
						$(MINIRUBY) $(srcdir)/ext/extmk.rb -n $(EXTMK_ARGS) install
 | 
				
			||||||
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
 | 
					install-doc: pre-install-doc do-install-doc post-install-doc
 | 
				
			||||||
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)
 | 
					do-install-doc: $(PROGRAM)
 | 
				
			||||||
	$(MINIRUBY) $(srcdir)/instruby.rb $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
 | 
					 | 
				
			||||||
post-install-doc::
 | 
					 | 
				
			||||||
	@$(NULLCMD)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
rdoc: $(PROGRAM) PHONY
 | 
					 | 
				
			||||||
	@echo Generating RDoc documentation
 | 
						@echo Generating RDoc documentation
 | 
				
			||||||
	$(RUNRUBY) "$(srcdir)/bin/rdoc" --all --ri --op "$(RDOCOUT)" "$(srcdir)"
 | 
						$(RUNRUBY) "$(srcdir)/bin/rdoc" --all --ri --op "$(RIDATADIR)" "$(srcdir)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
what-where-doc: no-install-doc
 | 
					pre-install: pre-install-local pre-install-ext
 | 
				
			||||||
no-install-doc: pre-no-install-doc dont-install-doc post-no-install-doc
 | 
					pre-install-local:: PHONY
 | 
				
			||||||
pre-no-install-doc:: install-prereq
 | 
					pre-install-ext:: PHONY
 | 
				
			||||||
dont-install-doc::
 | 
					pre-install-doc:: PHONY
 | 
				
			||||||
	$(MINIRUBY) $(srcdir)/instruby.rb -n $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
 | 
					 | 
				
			||||||
post-no-install-doc::
 | 
					 | 
				
			||||||
	@$(NULLCMD)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
install-prereq:
 | 
					post-install: post-install-local post-install-ext
 | 
				
			||||||
	@exit > $(INSTALLED_LIST)
 | 
					post-install-local:: PHONY
 | 
				
			||||||
 | 
					post-install-ext:: PHONY
 | 
				
			||||||
 | 
					post-install-doc:: PHONY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# no ext
 | 
				
			||||||
 | 
					# clean: clean-ext clean-local
 | 
				
			||||||
 | 
					clean: clean-local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
clean: clean-ext clean-local
 | 
					 | 
				
			||||||
clean-local::
 | 
					clean-local::
 | 
				
			||||||
	@$(RM) $(OBJS) $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
 | 
						@$(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:
 | 
					clean-ext:
 | 
				
			||||||
	@-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) clean
 | 
						@-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,15 +167,15 @@ check: test test-all
 | 
				
			||||||
test: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY
 | 
					test: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY
 | 
				
			||||||
	@$(MINIRUBY) $(srcdir)/rubytest.rb
 | 
						@$(MINIRUBY) $(srcdir)/rubytest.rb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test-all:
 | 
					test-all: miniruby$(EXEEXT) ruby
 | 
				
			||||||
	$(RUNRUBY) "$(srcdir)/test/runner.rb" --basedir="$(TESTSDIR)" --runner=$(TESTUI) $(TESTS)
 | 
						$(RUNRUBY) -C "$(srcdir)/test" runner.rb --runner=$(TESTUI) $(TESTS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extconf:
 | 
					extconf:
 | 
				
			||||||
	$(MINIRUBY) -I$(srcdir)/lib -run -e mkdir -- -p "$(EXTCONFDIR)"
 | 
						$(MINIRUBY) -I$(srcdir)/lib -run -e mkdir -- -p "$(EXTCONFDIR)"
 | 
				
			||||||
	$(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS)
 | 
						$(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(RBCONFIG): $(srcdir)/mkconfig.rb config.status $(PREP)
 | 
					$(RBCONFIG): $(srcdir)/mkconfig.rb config.status $(PREP)
 | 
				
			||||||
	@$(MINIRUBY) $(srcdir)/mkconfig.rb -timestamp=$@ \
 | 
						$(MINIRUBY) $(srcdir)/mkconfig.rb -timestamp=$@ \
 | 
				
			||||||
		-install_name=$(RUBY_INSTALL_NAME) \
 | 
							-install_name=$(RUBY_INSTALL_NAME) \
 | 
				
			||||||
		-so_name=$(RUBY_SO_NAME) rbconfig.rb
 | 
							-so_name=$(RUBY_SO_NAME) rbconfig.rb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -336,8 +211,6 @@ nt.$(OBJEXT): {$(VPATH)}nt.c
 | 
				
			||||||
x68.$(OBJEXT): {$(VPATH)}x68.c
 | 
					x68.$(OBJEXT): {$(VPATH)}x68.c
 | 
				
			||||||
os2.$(OBJEXT): {$(VPATH)}os2.c
 | 
					os2.$(OBJEXT): {$(VPATH)}os2.c
 | 
				
			||||||
dl_os2.$(OBJEXT): {$(VPATH)}dl_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" 
 | 
					# when I use -I., there is confliction at "OpenFile" 
 | 
				
			||||||
# so, set . into environment varible "include"
 | 
					# 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
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
 | 
				
			||||||
error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h config.h \
 | 
					error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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 \
 | 
					euc_jp.$(OBJEXT): {$(VPATH)}euc_jp.c {$(VPATH)}regenc.h \
 | 
				
			||||||
  {$(VPATH)}oniguruma.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)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
 | 
				
			||||||
  {$(VPATH)}node.h {$(VPATH)}env.h {$(VPATH)}util.h \
 | 
					  {$(VPATH)}node.h {$(VPATH)}util.h \
 | 
				
			||||||
  {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}dln.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)}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 \
 | 
					file.$(OBJEXT): {$(VPATH)}file.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
 | 
				
			||||||
  {$(VPATH)}rubyio.h {$(VPATH)}rubysig.h {$(VPATH)}util.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 \
 | 
					gc.$(OBJEXT): {$(VPATH)}gc.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
 | 
				
			||||||
  {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}node.h \
 | 
					  {$(VPATH)}rubysig.h {$(VPATH)}st.h {$(VPATH)}node.h \
 | 
				
			||||||
  {$(VPATH)}env.h {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}regint.h \
 | 
					  {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}yarvcore.h
 | 
				
			||||||
  {$(VPATH)}oniguruma.h
 | 
					 | 
				
			||||||
hash.$(OBJEXT): {$(VPATH)}hash.c {$(VPATH)}ruby.h config.h \
 | 
					hash.$(OBJEXT): {$(VPATH)}hash.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
 | 
				
			||||||
  {$(VPATH)}st.h {$(VPATH)}util.h {$(VPATH)}rubysig.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 \
 | 
					math.$(OBJEXT): {$(VPATH)}math.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
 | 
				
			||||||
numeric.$(OBJEXT): {$(VPATH)}numeric.c {$(VPATH)}ruby.h config.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
 | 
					  {$(VPATH)}missing.h
 | 
				
			||||||
object.$(OBJEXT): {$(VPATH)}object.c {$(VPATH)}ruby.h config.h \
 | 
					object.$(OBJEXT): {$(VPATH)}object.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
 | 
				
			||||||
parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}ruby.h config.h \
 | 
					parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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
 | 
					  {$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c
 | 
				
			||||||
prec.$(OBJEXT): {$(VPATH)}prec.c {$(VPATH)}ruby.h config.h \
 | 
					prec.$(OBJEXT): {$(VPATH)}prec.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
 | 
				
			||||||
re.$(OBJEXT): {$(VPATH)}re.c {$(VPATH)}ruby.h config.h \
 | 
					re.$(OBJEXT): {$(VPATH)}re.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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 \
 | 
					regcomp.$(OBJEXT): {$(VPATH)}regcomp.c {$(VPATH)}oniguruma.h \
 | 
				
			||||||
  {$(VPATH)}regint.h {$(VPATH)}regparse.h {$(VPATH)}regenc.h config.h
 | 
					  {$(VPATH)}regint.h {$(VPATH)}regparse.h {$(VPATH)}regenc.h config.h
 | 
				
			||||||
regenc.$(OBJEXT): {$(VPATH)}regenc.c {$(VPATH)}regint.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
 | 
					  {$(VPATH)}dln.h {$(VPATH)}node.h {$(VPATH)}util.h
 | 
				
			||||||
signal.$(OBJEXT): {$(VPATH)}signal.c {$(VPATH)}ruby.h config.h \
 | 
					signal.$(OBJEXT): {$(VPATH)}signal.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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 \
 | 
					sjis.$(OBJEXT): {$(VPATH)}sjis.c {$(VPATH)}regenc.h \
 | 
				
			||||||
  {$(VPATH)}oniguruma.h config.h
 | 
					  {$(VPATH)}oniguruma.h config.h
 | 
				
			||||||
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c {$(VPATH)}ruby.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
 | 
					st.$(OBJEXT): {$(VPATH)}st.c config.h {$(VPATH)}st.h
 | 
				
			||||||
string.$(OBJEXT): {$(VPATH)}string.c {$(VPATH)}ruby.h config.h \
 | 
					string.$(OBJEXT): {$(VPATH)}string.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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 \
 | 
					struct.$(OBJEXT): {$(VPATH)}struct.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
 | 
					  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
 | 
				
			||||||
time.$(OBJEXT): {$(VPATH)}time.c {$(VPATH)}ruby.h config.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
 | 
					  {$(VPATH)}util.h
 | 
				
			||||||
variable.$(OBJEXT): {$(VPATH)}variable.c {$(VPATH)}ruby.h config.h \
 | 
					variable.$(OBJEXT): {$(VPATH)}variable.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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 \
 | 
					version.$(OBJEXT): {$(VPATH)}version.c {$(VPATH)}ruby.h config.h \
 | 
				
			||||||
  {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										210
									
								
								compile.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								compile.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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_
 | 
				
			||||||
							
								
								
									
										15
									
								
								configure.in
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								configure.in
									
										
									
									
									
								
							| 
						 | 
					@ -71,6 +71,7 @@ fi
 | 
				
			||||||
if test "$program_prefix" = NONE; then
 | 
					if test "$program_prefix" = NONE; then
 | 
				
			||||||
  program_prefix=
 | 
					  program_prefix=
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AC_CANONICAL_TARGET
 | 
					AC_CANONICAL_TARGET
 | 
				
			||||||
target_os=`echo $target_os | sed 's/linux-gnu$/linux/;s/linux-gnu/linux-/'`
 | 
					target_os=`echo $target_os | sed 's/linux-gnu$/linux/;s/linux-gnu/linux-/'`
 | 
				
			||||||
ac_install_sh='' # unusable for extension libraries.
 | 
					ac_install_sh='' # unusable for extension libraries.
 | 
				
			||||||
| 
						 | 
					@ -183,7 +184,7 @@ cygwin*|mingw*)
 | 
				
			||||||
	AC_TRY_LINK([#include <stdio.h>],
 | 
						AC_TRY_LINK([#include <stdio.h>],
 | 
				
			||||||
		    [FILE* volatile f = stdin; return 0;],
 | 
							    [FILE* volatile f = stdin; return 0;],
 | 
				
			||||||
		    [rb_cv_msvcrt=`$OBJDUMP -p conftest$ac_exeext |
 | 
							    [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;}'`],
 | 
									   sed -n '/^[[ 	]]*dll name: \(msvc.*\)\.dll$/{s//\1/p;q;}'`],
 | 
				
			||||||
		    [rb_cv_msvcrt=msvcrt])
 | 
							    [rb_cv_msvcrt=msvcrt])
 | 
				
			||||||
	test "$rb_cv_msvcrt" = "" && 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,
 | 
					AC_ARG_ENABLE(pthread,
 | 
				
			||||||
       [  --enable-pthread        use pthread library.],
 | 
					       [  --enable-pthread        use pthread library.],
 | 
				
			||||||
       [enable_pthread=$enableval], [enable_pthread=no])
 | 
					       [enable_pthread=$enableval], [enable_pthread=yes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dnl Checks for libraries.
 | 
					dnl Checks for libraries.
 | 
				
			||||||
case "$target_os" in
 | 
					case "$target_os" in
 | 
				
			||||||
| 
						 | 
					@ -831,6 +832,8 @@ if test x"$ac_cv_header_ucontext_h" = xyes; then
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_CHECK_FUNCS(backtrace)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dnl default value for $KANJI
 | 
					dnl default value for $KANJI
 | 
				
			||||||
DEFAULT_KCODE="KCODE_NONE"
 | 
					DEFAULT_KCODE="KCODE_NONE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1004,11 +1007,11 @@ if test "$with_dln_a_out" != yes; then
 | 
				
			||||||
			    LDFLAGS='-brtl'
 | 
								    LDFLAGS='-brtl'
 | 
				
			||||||
			    XLDFLAGS='-bE:ruby.imp'
 | 
								    XLDFLAGS='-bE:ruby.imp'
 | 
				
			||||||
                        fi
 | 
					                        fi
 | 
				
			||||||
                        : ${ARCHFILE="ruby.imp"}
 | 
								: ${ARCHFILE="ruby.imp"}
 | 
				
			||||||
                        TRY_LINK='$(CC) $(LDFLAGS) -oconftest $(INCFLAGS) -I$(hdrdir) $(CPPFLAGS)'
 | 
					                        TRY_LINK='$(CC) $(LDFLAGS) -oconftest $(INCFLAGS) -I$(hdrdir) $(CPPFLAGS)'
 | 
				
			||||||
                        TRY_LINK="$TRY_LINK"' $(CFLAGS) $(src) $(LIBPATH) $(LOCAL_LIBS) $(LIBS)'
 | 
					                        TRY_LINK="$TRY_LINK"' $(CFLAGS) $(src) $(LIBPATH) $(LOCAL_LIBS) $(LIBS)'
 | 
				
			||||||
                        : ${LIBPATHENV=SHLIB_PATH}
 | 
								: ${LIBPATHENV=SHLIB_PATH}
 | 
				
			||||||
                        rb_cv_dlopen=yes ;;
 | 
								rb_cv_dlopen=yes ;;
 | 
				
			||||||
	human*)		: ${DLDFLAGS=''}
 | 
						human*)		: ${DLDFLAGS=''}
 | 
				
			||||||
			: ${LDSHARED=''}
 | 
								: ${LDSHARED=''}
 | 
				
			||||||
			: ${LDFLAGS=''}
 | 
								: ${LDFLAGS=''}
 | 
				
			||||||
| 
						 | 
					@ -1354,7 +1357,7 @@ if test "$enable_shared" = 'yes'; then
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
if test "$enable_rpath" = yes; then
 | 
					if test "$enable_rpath" = yes; then
 | 
				
			||||||
    if test "$GCC" = 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
 | 
					    else
 | 
				
			||||||
       LIBRUBYARG_SHARED='-R $(libdir) -L$(libdir) -L. '"$LIBRUBYARG_SHARED"
 | 
					       LIBRUBYARG_SHARED='-R $(libdir) -L$(libdir) -L. '"$LIBRUBYARG_SHARED"
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										71
									
								
								debug.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								debug.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								debug.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								debug.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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_
 | 
				
			||||||
							
								
								
									
										6917
									
								
								doc/ChangeLog-YARV
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6917
									
								
								doc/ChangeLog-YARV
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										57
									
								
								error.c
									
										
									
									
									
								
							
							
						
						
									
										57
									
								
								error.c
									
										
									
									
									
								
							| 
						 | 
					@ -11,8 +11,8 @@
 | 
				
			||||||
**********************************************************************/
 | 
					**********************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ruby.h"
 | 
					#include "ruby.h"
 | 
				
			||||||
#include "env.h"
 | 
					 | 
				
			||||||
#include "st.h"
 | 
					#include "st.h"
 | 
				
			||||||
 | 
					#include "yarv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
| 
						 | 
					@ -24,21 +24,23 @@
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const char ruby_version[], ruby_release_date[], ruby_platform[];
 | 
					extern const char ruby_version[], ruby_release_date[], ruby_platform[];
 | 
				
			||||||
 | 
					 | 
				
			||||||
int ruby_nerrs;
 | 
					int ruby_nerrs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *rb_sourcefile();
 | 
				
			||||||
 | 
					int rb_sourceline();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
err_position(char *buf, long len)
 | 
					err_position(char *buf, long len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ruby_set_current_source();
 | 
					    ruby_set_current_source();
 | 
				
			||||||
    if (!ruby_sourcefile) {
 | 
					    if (!rb_sourcefile()) {
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (ruby_sourceline == 0) {
 | 
					    else if (rb_sourceline() == 0) {
 | 
				
			||||||
	return snprintf(buf, len, "%s: ", ruby_sourcefile);
 | 
						return snprintf(buf, len, "%s: ", rb_sourcefile());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    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, ...)
 | 
					rb_compile_error(const char *fmt, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    va_list args;
 | 
					    va_list args;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    va_start(args, fmt);
 | 
					    va_start(args, fmt);
 | 
				
			||||||
    err_print(fmt, args);
 | 
					    err_print(fmt, args);
 | 
				
			||||||
    va_end(args);
 | 
					    va_end(args);
 | 
				
			||||||
| 
						 | 
					@ -147,6 +148,8 @@ rb_warn_m(VALUE self, VALUE mesg)
 | 
				
			||||||
    return Qnil;
 | 
					    return Qnil;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void yarv_bug();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
rb_bug(const char *fmt, ...)
 | 
					rb_bug(const char *fmt, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -157,6 +160,7 @@ rb_bug(const char *fmt, ...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (fwrite(buf, 1, len, out) == len ||
 | 
					    if (fwrite(buf, 1, len, out) == len ||
 | 
				
			||||||
	fwrite(buf, 1, len, (out = stdout)) == len) {
 | 
						fwrite(buf, 1, len, (out = stdout)) == len) {
 | 
				
			||||||
 | 
						yarv_bug();
 | 
				
			||||||
	fputs("[BUG] ", out);
 | 
						fputs("[BUG] ", out);
 | 
				
			||||||
	va_start(args, fmt);
 | 
						va_start(args, fmt);
 | 
				
			||||||
	vfprintf(out, fmt, args);
 | 
						vfprintf(out, fmt, args);
 | 
				
			||||||
| 
						 | 
					@ -164,6 +168,7 @@ rb_bug(const char *fmt, ...)
 | 
				
			||||||
	fprintf(out, "\nruby %s (%s) [%s]\n\n",
 | 
						fprintf(out, "\nruby %s (%s) [%s]\n\n",
 | 
				
			||||||
		ruby_version, ruby_release_date, ruby_platform);
 | 
							ruby_version, ruby_release_date, ruby_platform);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    abort();
 | 
					    abort();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,8 +195,6 @@ static struct types {
 | 
				
			||||||
    {T_SYMBOL,	"Symbol"},	/* :symbol */
 | 
					    {T_SYMBOL,	"Symbol"},	/* :symbol */
 | 
				
			||||||
    {T_DATA,	"Data"},	/* internal use: wrapped C pointers */
 | 
					    {T_DATA,	"Data"},	/* internal use: wrapped C pointers */
 | 
				
			||||||
    {T_MATCH,	"MatchData"},	/* data of $~ */
 | 
					    {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_NODE,	"Node"},	/* internal use: syntax tree node */
 | 
				
			||||||
    {T_UNDEF,	"undef"},	/* internal use: #undef; should not happen */
 | 
					    {T_UNDEF,	"undef"},	/* internal use: #undef; should not happen */
 | 
				
			||||||
    {-1,	0}
 | 
					    {-1,	0}
 | 
				
			||||||
| 
						 | 
					@ -1024,9 +1027,9 @@ rb_loaderror(const char *fmt, ...)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
rb_notimplement(void)
 | 
					rb_notimplement(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    rb_raise(rb_eNotImpError,
 | 
					  rb_raise(rb_eNotImpError,
 | 
				
			||||||
	     "The %s() function is unimplemented on this machine",
 | 
					           "The %s() function is unimplemented on this machine",
 | 
				
			||||||
	     rb_id2name(ruby_frame->callee));
 | 
						     rb_id2name(rb_frame_callee()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -1039,7 +1042,6 @@ rb_fatal(const char *fmt, ...)
 | 
				
			||||||
    vsnprintf(buf, BUFSIZ, fmt, args);
 | 
					    vsnprintf(buf, BUFSIZ, fmt, args);
 | 
				
			||||||
    va_end(args);
 | 
					    va_end(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ruby_in_eval = 0;
 | 
					 | 
				
			||||||
    rb_exc_fatal(rb_exc_new2(rb_eFatal, buf));
 | 
					    rb_exc_fatal(rb_exc_new2(rb_eFatal, buf));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1471,22 +1473,21 @@ Init_syserr(void)
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
err_append(const char *s)
 | 
					err_append(const char *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    extern VALUE ruby_errinfo;
 | 
					  yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					  if (th->parse_in_eval) {
 | 
				
			||||||
    if (ruby_in_eval) {
 | 
					    if (NIL_P(th->errinfo)) {
 | 
				
			||||||
	if (NIL_P(ruby_errinfo)) {
 | 
					      th->errinfo = rb_exc_new2(rb_eSyntaxError, s);
 | 
				
			||||||
	    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);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
	rb_write_error(s);
 | 
					      VALUE str = rb_obj_as_string(GET_THREAD()->errinfo);
 | 
				
			||||||
	rb_write_error("\n");
 | 
					
 | 
				
			||||||
 | 
					      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");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										250
									
								
								eval_error.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								eval_error.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,250 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * included by eval.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SET_CURRENT_SOURCE() ((void)0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_init_list(args, fmt);
 | 
				
			||||||
 | 
					    vsnprintf(buf, BUFSIZ, fmt, args);
 | 
				
			||||||
 | 
					    va_end(args);
 | 
				
			||||||
 | 
					    rb_write_error(buf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define warn_print(x) rb_write_error(x)
 | 
				
			||||||
 | 
					#define warn_print2(x,l) rb_write_error2(x,l)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					error_pos(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ruby_set_current_source();
 | 
				
			||||||
 | 
					    if (ruby_sourcefile) {
 | 
				
			||||||
 | 
						if (ruby_sourceline == 0) {
 | 
				
			||||||
 | 
						    warn_printf("%s", ruby_sourcefile);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (rb_frame_callee()) {
 | 
				
			||||||
 | 
						    warn_printf("%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
 | 
				
			||||||
 | 
								rb_id2name(rb_frame_callee()));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
						    warn_printf("%s:%d", ruby_sourcefile, ruby_sourceline);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					    char *einfo;
 | 
				
			||||||
 | 
					    long elen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (NIL_P(GET_THREAD()->errinfo))
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PUSH_TAG(PROT_NONE);
 | 
				
			||||||
 | 
					    if (EXEC_TAG() == 0) {
 | 
				
			||||||
 | 
						errat = get_backtrace(GET_THREAD()->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));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eclass = CLASS_OF(GET_THREAD()->errinfo);
 | 
				
			||||||
 | 
					    if (EXEC_TAG() == 0) {
 | 
				
			||||||
 | 
						e = rb_funcall(GET_THREAD()->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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    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;
 | 
				
			||||||
 | 
						long len = RARRAY_LEN(errat);
 | 
				
			||||||
 | 
						VALUE *ptr = RARRAY_PTR(errat);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
 | 
				
			||||||
 | 
					#define TRACE_HEAD 8
 | 
				
			||||||
 | 
					#define TRACE_TAIL 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 1; i < len; i++) {
 | 
				
			||||||
 | 
						    if (TYPE(ptr[i]) == T_STRING) {
 | 
				
			||||||
 | 
							warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    if (i == TRACE_HEAD && len > TRACE_MAX) {
 | 
				
			||||||
 | 
							warn_printf("\t ... %ld levels...\n",
 | 
				
			||||||
 | 
								    len - TRACE_HEAD - TRACE_TAIL);
 | 
				
			||||||
 | 
							i = len - TRACE_TAIL;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  error:
 | 
				
			||||||
 | 
					    POP_TAG();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					print_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));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE exception_error;
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (thread_set_raised(th))
 | 
				
			||||||
 | 
						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:
 | 
				
			||||||
 | 
						// TODO: fix me
 | 
				
			||||||
 | 
						error_pos();
 | 
				
			||||||
 | 
						warn_printf(": unexpected throw\n");
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					    case TAG_RAISE:
 | 
				
			||||||
 | 
					    case TAG_FATAL:
 | 
				
			||||||
 | 
						if (rb_obj_is_kind_of(GET_THREAD()->errinfo, rb_eSystemExit)) {
 | 
				
			||||||
 | 
						    status = sysexit_status(GET_THREAD()->errinfo);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
						    error_print();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
						rb_bug("Unknown longjmp status %d", ex);
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    thread_reset_raised(th);
 | 
				
			||||||
 | 
					    return status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										328
									
								
								eval_intern.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								eval_intern.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,328 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef EVAL_INTERN_H_INCLUDED
 | 
				
			||||||
 | 
					#define EVAL_INTERN_H_INCLUDED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PASS_PASSED_BLOCK() \
 | 
				
			||||||
 | 
					  (GET_THREAD()->passed_block = \
 | 
				
			||||||
 | 
					   GC_GUARDED_PTR_REF((yarv_block_t *)GET_THREAD()->cfp->lfp[0]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNSUPPORTED(func) \
 | 
				
			||||||
 | 
					{ \
 | 
				
			||||||
 | 
					  int *a = 0; \
 | 
				
			||||||
 | 
					  fprintf(stderr, "%s", "-- unsupported: " #func "\n"); fflush(stderr); \
 | 
				
			||||||
 | 
					  *a = 0; \
 | 
				
			||||||
 | 
					  rb_bug("unsupported: " #func); \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ruby.h"
 | 
				
			||||||
 | 
					#include "node.h"
 | 
				
			||||||
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					#include "rubysig.h"
 | 
				
			||||||
 | 
					#include "yarv.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 <setjmp.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
 | 
				
			||||||
 | 
					#  ifdef _AIX
 | 
				
			||||||
 | 
					#pragma alloca
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#   ifndef alloca		/* predefined by HP cc +Olibcalls */
 | 
				
			||||||
 | 
					void *alloca();
 | 
				
			||||||
 | 
					#   endif
 | 
				
			||||||
 | 
					#  endif /* AIX */
 | 
				
			||||||
 | 
					# endif	/* HAVE_ALLOCA_H */
 | 
				
			||||||
 | 
					#endif /* __GNUC__ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef HAVE_STRING_H
 | 
				
			||||||
 | 
					char *strrchr _((const char *, const char));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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 */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * FUNCTION_CALL_MAY_RETURN_TWICE 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 call before 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#if defined (__GNUC__) && (defined(sparc) || defined(__sparc__))
 | 
				
			||||||
 | 
					#define FUNCTION_CALL_MAY_RETURN_TWICE \
 | 
				
			||||||
 | 
					 ({ __asm__ volatile ("" : : :  \
 | 
				
			||||||
 | 
					    "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", \
 | 
				
			||||||
 | 
					    "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \
 | 
				
			||||||
 | 
					    "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); })
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					extern jmp_buf function_call_may_return_twice_jmp_buf;
 | 
				
			||||||
 | 
					extern int function_call_may_return_twice_false;
 | 
				
			||||||
 | 
					#define FUNCTION_CALL_MAY_RETURN_TWICE \
 | 
				
			||||||
 | 
					  (function_call_may_return_twice_false ? \
 | 
				
			||||||
 | 
					   setjmp(function_call_may_return_twice_jmp_buf) : \
 | 
				
			||||||
 | 
					   0)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#define ruby_longjmp(env, val) rb_jump_context(env, val)
 | 
				
			||||||
 | 
					#define ruby_setjmp(j) ((j)->status = 0, \
 | 
				
			||||||
 | 
					    FUNCTION_CALL_MAY_RETURN_TWICE, \
 | 
				
			||||||
 | 
					    getcontext(&(j)->context), \
 | 
				
			||||||
 | 
					    (j)->status)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#if !defined(setjmp) && defined(HAVE__SETJMP)
 | 
				
			||||||
 | 
					#define ruby_setjmp(env) _setjmp(env)
 | 
				
			||||||
 | 
					#define ruby_longjmp(env,val) _longjmp(env,val)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define ruby_setjmp(env) 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TH_PUSH_TAG(th) do { \
 | 
				
			||||||
 | 
					  yarv_thread_t * const _th = th; \
 | 
				
			||||||
 | 
					  struct yarv_tag _tag; \
 | 
				
			||||||
 | 
					  _tag.tag = 0; \
 | 
				
			||||||
 | 
					  _tag.prev = _th->tag; \
 | 
				
			||||||
 | 
					  _th->tag = &_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TH_POP_TAG() \
 | 
				
			||||||
 | 
					  _th->tag = _tag.prev; \
 | 
				
			||||||
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TH_POP_TAG2() \
 | 
				
			||||||
 | 
					  _th->tag = _tag.prev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PUSH_TAG(ptag) TH_PUSH_TAG(GET_THREAD())
 | 
				
			||||||
 | 
					#define POP_TAG()      TH_POP_TAG()
 | 
				
			||||||
 | 
					#define POP_TAG_INIT() } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PUSH_THREAD_TAG() \
 | 
				
			||||||
 | 
					  PUSH_TAG(PROT_THREAD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define POP_THREAD_TAG()  \
 | 
				
			||||||
 | 
					  POP_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 TH_EXEC_TAG() \
 | 
				
			||||||
 | 
					  (FLUSH_REGISTER_WINDOWS, ruby_setjmp(_th->tag->buf))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXEC_TAG() \
 | 
				
			||||||
 | 
					  TH_EXEC_TAG()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TH_JUMP_TAG(th, st) do { \
 | 
				
			||||||
 | 
					  ruby_longjmp(th->tag->buf,(st)); \
 | 
				
			||||||
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define JUMP_TAG(st) TH_JUMP_TAG(GET_THREAD(), st)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCOPE_TEST(f) \
 | 
				
			||||||
 | 
					  (ruby_cref()->nd_visi & (f))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCOPE_CHECK(f) \
 | 
				
			||||||
 | 
					  (ruby_cref()->nd_visi == (f))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SCOPE_SET(f)  \
 | 
				
			||||||
 | 
					{ \
 | 
				
			||||||
 | 
					  ruby_cref()->nd_visi = (f); \
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ruby_env {
 | 
				
			||||||
 | 
					    struct ruby_env *prev;
 | 
				
			||||||
 | 
					    struct FRAME *frame;
 | 
				
			||||||
 | 
					    struct SCOPE *scope;
 | 
				
			||||||
 | 
					    struct BLOCK *block;
 | 
				
			||||||
 | 
					    struct iter *iter;
 | 
				
			||||||
 | 
					    struct tag *tag;
 | 
				
			||||||
 | 
					    NODE *cref;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct thread *rb_thread_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern VALUE rb_cBinding;
 | 
				
			||||||
 | 
					extern VALUE rb_eThreadError;
 | 
				
			||||||
 | 
					extern VALUE rb_eLocalJumpError;
 | 
				
			||||||
 | 
					extern VALUE rb_eSysStackError;
 | 
				
			||||||
 | 
					extern VALUE exception_error;
 | 
				
			||||||
 | 
					extern VALUE sysstack_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rb_thread_cleanup _((void));
 | 
				
			||||||
 | 
					void rb_thread_wait_other_threads _((void));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int thread_set_raised(yarv_thread_t *th);
 | 
				
			||||||
 | 
					int thread_reset_raised(yarv_thread_t *th);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
 | 
				
			||||||
 | 
					VALUE rb_make_exception _((int argc, VALUE *argv));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NORETURN(void rb_raise_jump _((VALUE)));
 | 
				
			||||||
 | 
					NORETURN(void print_undef _((VALUE, ID)));
 | 
				
			||||||
 | 
					NORETURN(void th_localjump_error(const char *, VALUE, int));
 | 
				
			||||||
 | 
					NORETURN(void th_jump_tag_but_local_jump(int, VALUE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rb_thread_t rb_vm_curr_thread();
 | 
				
			||||||
 | 
					VALUE th_compile(yarv_thread_t *th, VALUE str, VALUE file, VALUE line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NODE *th_get_cref(yarv_thread_t *th, yarv_iseq_t *iseq, yarv_control_frame_t *cfp);
 | 
				
			||||||
 | 
					NODE *th_cref_push(yarv_thread_t *th, VALUE, int);
 | 
				
			||||||
 | 
					NODE *th_set_special_cref(yarv_thread_t *th, VALUE *lfp, NODE * cref_stack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static yarv_control_frame_t *
 | 
				
			||||||
 | 
					th_get_ruby_level_cfp(yarv_thread_t *th, yarv_control_frame_t *cfp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    yarv_iseq_t *iseq = 0;
 | 
				
			||||||
 | 
					    while (!YARV_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
 | 
				
			||||||
 | 
						if (YARV_NORMAL_ISEQ_P(cfp->iseq)) {
 | 
				
			||||||
 | 
						    iseq = cfp->iseq;
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cfp = YARV_PREVIOUS_CONTROL_FRAME(cfp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!iseq) {
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return cfp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static NODE *
 | 
				
			||||||
 | 
					ruby_cref()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					    yarv_control_frame_t *cfp = th_get_ruby_level_cfp(th, th->cfp);
 | 
				
			||||||
 | 
					    return th_get_cref(th, cfp->iseq, cfp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE th_get_cbase(yarv_thread_t *th);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ruby_cbase() th_get_cbase(GET_THREAD())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* EVAL_INTERN_H_INCLUDED */
 | 
				
			||||||
							
								
								
									
										411
									
								
								eval_jump.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								eval_jump.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,411 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * from eval.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eval_intern.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NORETURN(static VALUE rb_f_throw _((int, VALUE *)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     throw(symbol [, obj])
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Transfers control to the end of the active +catch+ block
 | 
				
			||||||
 | 
					 *  waiting for _symbol_. Raises +NameError+ if there
 | 
				
			||||||
 | 
					 *  is no +catch+ block for the symbol. The optional second
 | 
				
			||||||
 | 
					 *  parameter supplies a return value for the +catch+ block,
 | 
				
			||||||
 | 
					 *  which otherwise defaults to +nil+. For examples, see
 | 
				
			||||||
 | 
					 *  <code>Kernel::catch</code>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_f_throw(int argc, VALUE *argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE tag, value;
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					    struct yarv_tag *tt = th->tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_scan_args(argc, argv, "11", &tag, &value);
 | 
				
			||||||
 | 
					    tag = ID2SYM(rb_to_id(tag));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (tt) {
 | 
				
			||||||
 | 
						if (tt->tag == tag) {
 | 
				
			||||||
 | 
						    tt->retval = value;
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tt = tt->prev;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!tt) {
 | 
				
			||||||
 | 
						rb_name_error(SYM2ID(tag), "uncaught throw `%s'",
 | 
				
			||||||
 | 
							      rb_id2name(SYM2ID(tag)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rb_trap_restore_mask();
 | 
				
			||||||
 | 
					    th->errinfo = tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JUMP_TAG(TAG_THROW);
 | 
				
			||||||
 | 
					#ifndef __GNUC__
 | 
				
			||||||
 | 
					    return Qnil;		/* not reached */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_throw(const char *tag, VALUE val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE argv[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    argv[0] = ID2SYM(rb_intern(tag));
 | 
				
			||||||
 | 
					    argv[1] = val;
 | 
				
			||||||
 | 
					    rb_f_throw(2, argv);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     catch(symbol) {| | block }  > obj
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  +catch+ executes its block. If a +throw+ is
 | 
				
			||||||
 | 
					 *  executed, Ruby searches up its stack for a +catch+ block
 | 
				
			||||||
 | 
					 *  with a tag corresponding to the +throw+'s
 | 
				
			||||||
 | 
					 *  _symbol_. If found, that block is terminated, and
 | 
				
			||||||
 | 
					 *  +catch+ returns the value given to +throw+. If
 | 
				
			||||||
 | 
					 *  +throw+ is not called, the block terminates normally, and
 | 
				
			||||||
 | 
					 *  the value of +catch+ is the value of the last expression
 | 
				
			||||||
 | 
					 *  evaluated. +catch+ expressions may be nested, and the
 | 
				
			||||||
 | 
					 *  +throw+ call need not be in lexical scope.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     def routine(n)
 | 
				
			||||||
 | 
					 *       puts n
 | 
				
			||||||
 | 
					 *       throw :done if n <= 0
 | 
				
			||||||
 | 
					 *       routine(n-1)
 | 
				
			||||||
 | 
					 *     end
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     catch(:done) { routine(3) }
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     3
 | 
				
			||||||
 | 
					 *     2
 | 
				
			||||||
 | 
					 *     1
 | 
				
			||||||
 | 
					 *     0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_f_catch(VALUE dmy, VALUE tag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int state;
 | 
				
			||||||
 | 
					    VALUE val = Qnil;		/* OK */
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tag = ID2SYM(rb_to_id(tag));
 | 
				
			||||||
 | 
					    PUSH_TAG(tag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    th->tag->tag = tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((state = EXEC_TAG()) == 0) {
 | 
				
			||||||
 | 
						val = rb_yield_0(tag, 0, 0, 0, Qfalse);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (state == TAG_THROW && th->errinfo == tag) {
 | 
				
			||||||
 | 
						val = th->tag->retval;
 | 
				
			||||||
 | 
						th->errinfo = 0;
 | 
				
			||||||
 | 
						state = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    POP_TAG();
 | 
				
			||||||
 | 
					    if (state)
 | 
				
			||||||
 | 
						JUMP_TAG(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					catch_i(VALUE tag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_catch(const char *tag, VALUE (*func)(), VALUE data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return rb_iterate((VALUE (*)_((VALUE)))catch_i, ID2SYM(rb_intern(tag)),
 | 
				
			||||||
 | 
							      func, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* exit */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NORETURN(static VALUE terminate_process _((int, const char *, long)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					terminate_process(int status, const char *mesg, long mlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE args[2];
 | 
				
			||||||
 | 
					    yarv_vm_t *vm = GET_THREAD()->vm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    args[0] = INT2NUM(status);
 | 
				
			||||||
 | 
					    args[1] = rb_str_new(mesg, mlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vm->exit_code = status;
 | 
				
			||||||
 | 
					    rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_exit(int status)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (GET_THREAD()->tag) {
 | 
				
			||||||
 | 
						terminate_process(status, "exit", 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ruby_finalize();
 | 
				
			||||||
 | 
					    exit(status);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     exit(integer=0)
 | 
				
			||||||
 | 
					 *     Kernel::exit(integer=0)
 | 
				
			||||||
 | 
					 *     Process::exit(integer=0)
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Initiates the termination of the Ruby script by raising the
 | 
				
			||||||
 | 
					 *  <code>SystemExit</code> exception. This exception may be caught. The
 | 
				
			||||||
 | 
					 *  optional parameter is used to return a status code to the invoking
 | 
				
			||||||
 | 
					 *  environment.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     begin
 | 
				
			||||||
 | 
					 *       exit
 | 
				
			||||||
 | 
					 *       puts "never get here"
 | 
				
			||||||
 | 
					 *     rescue SystemExit
 | 
				
			||||||
 | 
					 *       puts "rescued a SystemExit exception"
 | 
				
			||||||
 | 
					 *     end
 | 
				
			||||||
 | 
					 *     puts "after begin block"
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     rescued a SystemExit exception
 | 
				
			||||||
 | 
					 *     after begin block
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  Just prior to termination, Ruby executes any <code>at_exit</code> functions
 | 
				
			||||||
 | 
					 *  (see Kernel::at_exit) and runs any object finalizers (see
 | 
				
			||||||
 | 
					 *  ObjectSpace::define_finalizer).
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     at_exit { puts "at_exit function" }
 | 
				
			||||||
 | 
					 *     ObjectSpace.define_finalizer("string",  proc { puts "in finalizer" })
 | 
				
			||||||
 | 
					 *     exit
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     at_exit function
 | 
				
			||||||
 | 
					 *     in finalizer
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_f_exit(int argc, VALUE *argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE status;
 | 
				
			||||||
 | 
					    int istatus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_secure(4);
 | 
				
			||||||
 | 
					    if (rb_scan_args(argc, argv, "01", &status) == 1) {
 | 
				
			||||||
 | 
						switch (status) {
 | 
				
			||||||
 | 
						case Qtrue:
 | 
				
			||||||
 | 
						    istatus = EXIT_SUCCESS;
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						case Qfalse:
 | 
				
			||||||
 | 
						    istatus = EXIT_FAILURE;
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
						    istatus = NUM2INT(status);
 | 
				
			||||||
 | 
					#if EXIT_SUCCESS != 0
 | 
				
			||||||
 | 
						    if (istatus == 0)
 | 
				
			||||||
 | 
							istatus = EXIT_SUCCESS;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						istatus = EXIT_SUCCESS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rb_exit(istatus);
 | 
				
			||||||
 | 
					    return Qnil;		/* not reached */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     abort
 | 
				
			||||||
 | 
					 *     Kernel::abort
 | 
				
			||||||
 | 
					 *     Process::abort
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Terminate execution immediately, effectively by calling
 | 
				
			||||||
 | 
					 *  <code>Kernel.exit(1)</code>. If _msg_ is given, it is written
 | 
				
			||||||
 | 
					 *  to STDERR prior to terminating.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_f_abort(int argc, VALUE *argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_secure(4);
 | 
				
			||||||
 | 
					    if (argc == 0) {
 | 
				
			||||||
 | 
						if (!NIL_P(GET_THREAD()->errinfo)) {
 | 
				
			||||||
 | 
						    error_print();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rb_exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						VALUE mesg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rb_scan_args(argc, argv, "1", &mesg);
 | 
				
			||||||
 | 
						StringValue(argv[0]);
 | 
				
			||||||
 | 
						rb_io_puts(argc, argv, rb_stderr);
 | 
				
			||||||
 | 
						terminate_process(EXIT_FAILURE, RSTRING_PTR(argv[0]),
 | 
				
			||||||
 | 
								  RSTRING_LEN(argv[0]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return Qnil;		/* not reached */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void call_end_proc _((VALUE data));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					call_end_proc(VALUE data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // TODO: fix me
 | 
				
			||||||
 | 
					    proc_invoke(data, rb_ary_new2(0), Qundef, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     at_exit { block } -> proc
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Converts _block_ to a +Proc+ object (and therefore
 | 
				
			||||||
 | 
					 *  binds it at the point of call) and registers it for execution when
 | 
				
			||||||
 | 
					 *  the program exits. If multiple handlers are registered, they are
 | 
				
			||||||
 | 
					 *  executed in reverse order of registration.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     def do_at_exit(str1)
 | 
				
			||||||
 | 
					 *       at_exit { print str1 }
 | 
				
			||||||
 | 
					 *     end
 | 
				
			||||||
 | 
					 *     at_exit { puts "cruel world" }
 | 
				
			||||||
 | 
					 *     do_at_exit("goodbye ")
 | 
				
			||||||
 | 
					 *     exit
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     goodbye cruel world
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_f_at_exit(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE proc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!rb_block_given_p()) {
 | 
				
			||||||
 | 
						rb_raise(rb_eArgError, "called without a block");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    proc = rb_block_proc();
 | 
				
			||||||
 | 
					    rb_set_end_proc(call_end_proc, proc);
 | 
				
			||||||
 | 
					    return proc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct end_proc_data {
 | 
				
			||||||
 | 
					    void (*func) ();
 | 
				
			||||||
 | 
					    VALUE data;
 | 
				
			||||||
 | 
					    int safe;
 | 
				
			||||||
 | 
					    struct end_proc_data *next;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct end_proc_data *end_procs, *ephemeral_end_procs, *tmp_end_procs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_set_end_proc(void (*func)(VALUE), VALUE data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct end_proc_data *link = ALLOC(struct end_proc_data);
 | 
				
			||||||
 | 
					    struct end_proc_data **list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ruby_wrapper) {
 | 
				
			||||||
 | 
						list = &ephemeral_end_procs;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						list = &end_procs;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    link->next = *list;
 | 
				
			||||||
 | 
					    link->func = func;
 | 
				
			||||||
 | 
					    link->data = data;
 | 
				
			||||||
 | 
					    link->safe = rb_safe_level();
 | 
				
			||||||
 | 
					    *list = link;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_mark_end_proc(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct end_proc_data *link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    link = end_procs;
 | 
				
			||||||
 | 
					    while (link) {
 | 
				
			||||||
 | 
						rb_gc_mark(link->data);
 | 
				
			||||||
 | 
						link = link->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    link = ephemeral_end_procs;
 | 
				
			||||||
 | 
					    while (link) {
 | 
				
			||||||
 | 
						rb_gc_mark(link->data);
 | 
				
			||||||
 | 
						link = link->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    link = tmp_end_procs;
 | 
				
			||||||
 | 
					    while (link) {
 | 
				
			||||||
 | 
						rb_gc_mark(link->data);
 | 
				
			||||||
 | 
						link = link->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_exec_end_proc(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct end_proc_data *link, *tmp;
 | 
				
			||||||
 | 
					    int status;
 | 
				
			||||||
 | 
					    volatile int safe = rb_safe_level();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (ephemeral_end_procs) {
 | 
				
			||||||
 | 
						tmp_end_procs = link = ephemeral_end_procs;
 | 
				
			||||||
 | 
						ephemeral_end_procs = 0;
 | 
				
			||||||
 | 
						while (link) {
 | 
				
			||||||
 | 
						    PUSH_TAG(PROT_NONE);
 | 
				
			||||||
 | 
						    if ((status = EXEC_TAG()) == 0) {
 | 
				
			||||||
 | 
							rb_set_safe_level_force(link->safe);
 | 
				
			||||||
 | 
							(*link->func) (link->data);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    POP_TAG();
 | 
				
			||||||
 | 
						    if (status) {
 | 
				
			||||||
 | 
							error_handle(status);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    tmp = link;
 | 
				
			||||||
 | 
						    tmp_end_procs = link = link->next;
 | 
				
			||||||
 | 
						    free(tmp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    while (end_procs) {
 | 
				
			||||||
 | 
						tmp_end_procs = link = end_procs;
 | 
				
			||||||
 | 
						end_procs = 0;
 | 
				
			||||||
 | 
						while (link) {
 | 
				
			||||||
 | 
						    PUSH_TAG(PROT_NONE);
 | 
				
			||||||
 | 
						    if ((status = EXEC_TAG()) == 0) {
 | 
				
			||||||
 | 
							rb_set_safe_level_force(link->safe);
 | 
				
			||||||
 | 
							(*link->func) (link->data);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    POP_TAG();
 | 
				
			||||||
 | 
						    if (status) {
 | 
				
			||||||
 | 
							error_handle(status);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    tmp = link;
 | 
				
			||||||
 | 
						    tmp_end_procs = link = link->next;
 | 
				
			||||||
 | 
						    free(tmp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rb_set_safe_level_force(safe);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					Init_jump()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_define_global_function("catch", rb_f_catch, 1);
 | 
				
			||||||
 | 
					    rb_define_global_function("throw", rb_f_throw, -1);
 | 
				
			||||||
 | 
					    rb_define_global_function("exit", rb_f_exit, -1);
 | 
				
			||||||
 | 
					    rb_define_global_function("abort", rb_f_abort, -1);
 | 
				
			||||||
 | 
					    rb_define_global_function("at_exit", rb_f_at_exit, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										508
									
								
								eval_load.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										508
									
								
								eval_load.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,508 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * load methods from eval.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eval_intern.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern VALUE ruby_top_self;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE ruby_dln_librefs;
 | 
				
			||||||
 | 
					static VALUE rb_features;
 | 
				
			||||||
 | 
					static st_table *loading_tbl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NORETURN(void jump_tag_but_local_jump(int, VALUE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0)
 | 
				
			||||||
 | 
					#ifdef DLEXT2
 | 
				
			||||||
 | 
					#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0 || strcmp(e, DLEXT2) == 0)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					rb_feature_p(const char *feature, const char *ext, int rb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE v;
 | 
				
			||||||
 | 
					    char *f, *e;
 | 
				
			||||||
 | 
					    long i, len, elen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ext) {
 | 
				
			||||||
 | 
						len = ext - feature;
 | 
				
			||||||
 | 
						elen = strlen(ext);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						len = strlen(feature);
 | 
				
			||||||
 | 
						elen = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (i = 0; i < RARRAY_LEN(rb_features); ++i) {
 | 
				
			||||||
 | 
						v = RARRAY_PTR(rb_features)[i];
 | 
				
			||||||
 | 
						f = StringValuePtr(v);
 | 
				
			||||||
 | 
						if (strncmp(f, feature, len) != 0)
 | 
				
			||||||
 | 
						    continue;
 | 
				
			||||||
 | 
						if (!*(e = f + len)) {
 | 
				
			||||||
 | 
						    if (ext)
 | 
				
			||||||
 | 
							continue;
 | 
				
			||||||
 | 
						    return 'u';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (*e != '.')
 | 
				
			||||||
 | 
						    continue;
 | 
				
			||||||
 | 
						if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
 | 
				
			||||||
 | 
						    return 's';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((rb || !ext) && (strcmp(e, ".rb") == 0)) {
 | 
				
			||||||
 | 
						    return 'r';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *const loadable_ext[] = {
 | 
				
			||||||
 | 
					    ".rb", DLEXT,
 | 
				
			||||||
 | 
					#ifdef DLEXT2
 | 
				
			||||||
 | 
					    DLEXT2,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    0
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int search_required _((VALUE, VALUE *));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					rb_provided(const char *feature)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    char *buf;
 | 
				
			||||||
 | 
					    VALUE fname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rb_feature_p(feature, 0, Qfalse))
 | 
				
			||||||
 | 
						return Qtrue;
 | 
				
			||||||
 | 
					    if (loading_tbl) {
 | 
				
			||||||
 | 
						if (st_lookup(loading_tbl, (st_data_t) feature, 0))
 | 
				
			||||||
 | 
						    return Qtrue;
 | 
				
			||||||
 | 
						buf = ALLOCA_N(char, strlen(feature) + 8);
 | 
				
			||||||
 | 
						strcpy(buf, feature);
 | 
				
			||||||
 | 
						for (i = 0; loadable_ext[i]; i++) {
 | 
				
			||||||
 | 
						    strcpy(buf + strlen(feature), loadable_ext[i]);
 | 
				
			||||||
 | 
						    if (st_lookup(loading_tbl, (st_data_t) buf, 0))
 | 
				
			||||||
 | 
							return Qtrue;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (search_required(rb_str_new2(feature), &fname)) {
 | 
				
			||||||
 | 
						feature = RSTRING_PTR(fname);
 | 
				
			||||||
 | 
						if (rb_feature_p(feature, 0, Qfalse))
 | 
				
			||||||
 | 
						    return Qtrue;
 | 
				
			||||||
 | 
						if (loading_tbl && st_lookup(loading_tbl, (st_data_t) feature, 0))
 | 
				
			||||||
 | 
						    return Qtrue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return Qfalse;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					rb_provide_feature(VALUE feature)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_ary_push(rb_features, feature);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_provide(const char *feature)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_provide_feature(rb_str_new2(feature));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE rb_load_path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NORETURN(static void load_failed _((VALUE)));
 | 
				
			||||||
 | 
					void th_klass_init(yarv_thread_t *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_load(VALUE fname, int wrap)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE tmp;
 | 
				
			||||||
 | 
					    int state;
 | 
				
			||||||
 | 
					    volatile VALUE self = ruby_top_self;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FilePathValue(fname);
 | 
				
			||||||
 | 
					    fname = rb_str_new4(fname);
 | 
				
			||||||
 | 
					    tmp = rb_find_file(fname);
 | 
				
			||||||
 | 
					    if (!tmp) {
 | 
				
			||||||
 | 
						load_failed(fname);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fname = tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GET_THREAD()->errinfo = Qnil;	/* ensure */
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (!wrap) {
 | 
				
			||||||
 | 
						rb_secure(4);		/* should alter global state */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						/* load in anonymous module as toplevel */
 | 
				
			||||||
 | 
						self = rb_obj_clone(ruby_top_self);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PUSH_TAG(PROT_NONE);
 | 
				
			||||||
 | 
					    state = EXEC_TAG();
 | 
				
			||||||
 | 
					    if (state == 0) {
 | 
				
			||||||
 | 
						yarv_load(RSTRING_PTR(fname));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    POP_TAG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ruby_nerrs > 0) {
 | 
				
			||||||
 | 
						ruby_nerrs = 0;
 | 
				
			||||||
 | 
						rb_exc_raise(GET_THREAD()->errinfo);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (state) {
 | 
				
			||||||
 | 
						th_jump_tag_but_local_jump(state, Qundef);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!NIL_P(GET_THREAD()->errinfo)) {
 | 
				
			||||||
 | 
						/* exception during load */
 | 
				
			||||||
 | 
						rb_exc_raise(GET_THREAD()->errinfo);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_load_protect(VALUE fname, int wrap, int *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PUSH_THREAD_TAG();
 | 
				
			||||||
 | 
					    if ((status = EXEC_TAG()) == 0) {
 | 
				
			||||||
 | 
						rb_load(fname, wrap);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    POP_THREAD_TAG();
 | 
				
			||||||
 | 
					    if (state)
 | 
				
			||||||
 | 
						*state = status;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     load(filename, wrap=false)   => true
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Loads and executes the Ruby
 | 
				
			||||||
 | 
					 *  program in the file _filename_. If the filename does not
 | 
				
			||||||
 | 
					 *  resolve to an absolute path, the file is searched for in the library
 | 
				
			||||||
 | 
					 *  directories listed in <code>$:</code>. If the optional _wrap_
 | 
				
			||||||
 | 
					 *  parameter is +true+, the loaded script will be executed
 | 
				
			||||||
 | 
					 *  under an anonymous module, protecting the calling program's global
 | 
				
			||||||
 | 
					 *  namespace. In no circumstance will any local variables in the loaded
 | 
				
			||||||
 | 
					 *  file be propagated to the loading environment.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_f_load(argc, argv)
 | 
				
			||||||
 | 
					    int argc;
 | 
				
			||||||
 | 
					    VALUE *argv;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE fname, wrap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_scan_args(argc, argv, "11", &fname, &wrap);
 | 
				
			||||||
 | 
					    rb_load(fname, RTEST(wrap));
 | 
				
			||||||
 | 
					    return Qtrue;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					load_wait(char *ftptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    st_data_t th;
 | 
				
			||||||
 | 
					    if (!loading_tbl) {
 | 
				
			||||||
 | 
						return Qfalse;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!st_lookup(loading_tbl, (st_data_t) ftptr, &th)) {
 | 
				
			||||||
 | 
						return Qfalse;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: write wait routine
 | 
				
			||||||
 | 
					    return Qtrue;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     require(string)    => true or false
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Ruby tries to load the library named _string_, returning
 | 
				
			||||||
 | 
					 *  +true+ if successful. If the filename does not resolve to
 | 
				
			||||||
 | 
					 *  an absolute path, it will be searched for in the directories listed
 | 
				
			||||||
 | 
					 *  in <code>$:</code>. If the file has the extension ``.rb'', it is
 | 
				
			||||||
 | 
					 *  loaded as a source file; if the extension is ``.so'', ``.o'', or
 | 
				
			||||||
 | 
					 *  ``.dll'', or whatever the default shared library extension is on
 | 
				
			||||||
 | 
					 *  the current platform, Ruby loads the shared library as a Ruby
 | 
				
			||||||
 | 
					 *  extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
 | 
				
			||||||
 | 
					 *  to the name. The name of the loaded feature is added to the array in
 | 
				
			||||||
 | 
					 *  <code>$"</code>. A feature will not be loaded if it's name already
 | 
				
			||||||
 | 
					 *  appears in <code>$"</code>. However, the file name is not converted
 | 
				
			||||||
 | 
					 *  to an absolute path, so that ``<code>require 'a';require
 | 
				
			||||||
 | 
					 *  './a'</code>'' will load <code>a.rb</code> twice.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     require "my-library.rb"
 | 
				
			||||||
 | 
					 *     require "db-driver"
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_f_require(VALUE obj, VALUE fname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return rb_require_safe(fname, rb_safe_level());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					search_required(VALUE fname, VALUE *path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE tmp;
 | 
				
			||||||
 | 
					    char *ext, *ftptr;
 | 
				
			||||||
 | 
					    int type, ft = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *path = 0;
 | 
				
			||||||
 | 
					    ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
 | 
				
			||||||
 | 
					    if (ext && !strchr(ext, '/')) {
 | 
				
			||||||
 | 
						if (strcmp(".rb", ext) == 0) {
 | 
				
			||||||
 | 
						    if (rb_feature_p(ftptr, ext, Qtrue))
 | 
				
			||||||
 | 
							return 'r';
 | 
				
			||||||
 | 
						    if (tmp = rb_find_file(fname)) {
 | 
				
			||||||
 | 
							tmp = rb_file_expand_path(tmp, Qnil);
 | 
				
			||||||
 | 
							ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
 | 
				
			||||||
 | 
							if (!rb_feature_p(ftptr, ext, Qtrue))
 | 
				
			||||||
 | 
							    *path = tmp;
 | 
				
			||||||
 | 
							return 'r';
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (IS_SOEXT(ext)) {
 | 
				
			||||||
 | 
						    if (rb_feature_p(ftptr, ext, Qfalse))
 | 
				
			||||||
 | 
							return 's';
 | 
				
			||||||
 | 
						    tmp = rb_str_new(RSTRING_PTR(fname), ext - RSTRING_PTR(fname));
 | 
				
			||||||
 | 
					#ifdef DLEXT2
 | 
				
			||||||
 | 
						    OBJ_FREEZE(tmp);
 | 
				
			||||||
 | 
						    if (rb_find_file_ext(&tmp, loadable_ext + 1)) {
 | 
				
			||||||
 | 
							tmp = rb_file_expand_path(tmp, Qnil);
 | 
				
			||||||
 | 
							ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
 | 
				
			||||||
 | 
							if (!rb_feature_p(ftptr, ext, Qfalse))
 | 
				
			||||||
 | 
							    *path = tmp;
 | 
				
			||||||
 | 
							return 's';
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						    rb_str_cat2(tmp, DLEXT);
 | 
				
			||||||
 | 
						    OBJ_FREEZE(tmp);
 | 
				
			||||||
 | 
						    if (tmp = rb_find_file(tmp)) {
 | 
				
			||||||
 | 
							tmp = rb_file_expand_path(tmp, Qnil);
 | 
				
			||||||
 | 
							ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
 | 
				
			||||||
 | 
							if (!rb_feature_p(ftptr, ext, Qfalse))
 | 
				
			||||||
 | 
							    *path = tmp;
 | 
				
			||||||
 | 
							return 's';
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (IS_DLEXT(ext)) {
 | 
				
			||||||
 | 
						    if (rb_feature_p(ftptr, ext, Qfalse))
 | 
				
			||||||
 | 
							return 's';
 | 
				
			||||||
 | 
						    if (tmp = rb_find_file(fname)) {
 | 
				
			||||||
 | 
							tmp = rb_file_expand_path(tmp, Qnil);
 | 
				
			||||||
 | 
							ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
 | 
				
			||||||
 | 
							if (!rb_feature_p(ftptr, ext, Qfalse))
 | 
				
			||||||
 | 
							    *path = tmp;
 | 
				
			||||||
 | 
							return 's';
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if ((ft = rb_feature_p(ftptr, 0, Qfalse)) == 'r') {
 | 
				
			||||||
 | 
						return 'r';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    tmp = fname;
 | 
				
			||||||
 | 
					    type = rb_find_file_ext(&tmp, loadable_ext);
 | 
				
			||||||
 | 
					    tmp = rb_file_expand_path(tmp, Qnil);
 | 
				
			||||||
 | 
					    switch (type) {
 | 
				
			||||||
 | 
					    case 0:
 | 
				
			||||||
 | 
						ftptr = RSTRING_PTR(tmp);
 | 
				
			||||||
 | 
						if (ft)
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						return rb_feature_p(ftptr, 0, Qfalse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
						if (ft)
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
					    case 1:
 | 
				
			||||||
 | 
						ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
 | 
				
			||||||
 | 
						if (rb_feature_p(ftptr, ext, !--type))
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						*path = tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return type ? 's' : 'r';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					load_failed(VALUE fname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_raise(rb_eLoadError, "no such file to load -- %s",
 | 
				
			||||||
 | 
						     RSTRING_PTR(fname));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_require_safe(VALUE fname, int safe)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE result = Qnil;
 | 
				
			||||||
 | 
					    volatile VALUE errinfo = GET_THREAD()->errinfo;
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					    int state;
 | 
				
			||||||
 | 
					    char *volatile ftptr = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PUSH_TAG(PROT_NONE);
 | 
				
			||||||
 | 
					    if ((state = EXEC_TAG()) == 0) {
 | 
				
			||||||
 | 
						VALUE path;
 | 
				
			||||||
 | 
						long handle;
 | 
				
			||||||
 | 
						int found;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rb_set_safe_level_force(safe);
 | 
				
			||||||
 | 
						FilePathValue(fname);
 | 
				
			||||||
 | 
						*(volatile VALUE *)&fname = rb_str_new4(fname);
 | 
				
			||||||
 | 
						found = search_required(fname, &path);
 | 
				
			||||||
 | 
						if (found) {
 | 
				
			||||||
 | 
						    if (!path || load_wait(RSTRING_PTR(path))) {
 | 
				
			||||||
 | 
							result = Qfalse;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    else {
 | 
				
			||||||
 | 
							rb_set_safe_level_force(0);
 | 
				
			||||||
 | 
							switch (found) {
 | 
				
			||||||
 | 
							case 'r':
 | 
				
			||||||
 | 
							    /* loading ruby library should be serialized. */
 | 
				
			||||||
 | 
							    if (!loading_tbl) {
 | 
				
			||||||
 | 
								loading_tbl = st_init_strtable();
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
							    /* partial state */
 | 
				
			||||||
 | 
							    ftptr = ruby_strdup(RSTRING_PTR(path));
 | 
				
			||||||
 | 
							    st_insert(loading_tbl, (st_data_t) ftptr,
 | 
				
			||||||
 | 
								      (st_data_t) GET_THREAD()->self);
 | 
				
			||||||
 | 
							    rb_load(path, 0);
 | 
				
			||||||
 | 
							    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 's':
 | 
				
			||||||
 | 
							    ruby_current_node = 0;
 | 
				
			||||||
 | 
							    ruby_sourcefile = rb_source_filename(RSTRING_PTR(path));
 | 
				
			||||||
 | 
							    ruby_sourceline = 0;
 | 
				
			||||||
 | 
							    //SCOPE_SET(NOEX_PUBLIC);
 | 
				
			||||||
 | 
							    handle = (long)dln_load(RSTRING_PTR(path));
 | 
				
			||||||
 | 
							    rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
 | 
				
			||||||
 | 
							    break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rb_provide_feature(path);
 | 
				
			||||||
 | 
							result = Qtrue;
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    POP_TAG();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ftptr) {
 | 
				
			||||||
 | 
						if (st_delete(loading_tbl, (st_data_t *) & ftptr, 0)) {	/* loading done */
 | 
				
			||||||
 | 
						    free(ftptr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (state) {
 | 
				
			||||||
 | 
						JUMP_TAG(state);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (NIL_P(result)) {
 | 
				
			||||||
 | 
						load_failed(fname);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    th->errinfo = errinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_require(const char *fname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE fn = rb_str_new2(fname);
 | 
				
			||||||
 | 
					    OBJ_FREEZE(fn);
 | 
				
			||||||
 | 
					    return rb_require_safe(fn, rb_safe_level());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     mod.autoload(name, filename)   => nil
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Registers _filename_ to be loaded (using <code>Kernel::require</code>)
 | 
				
			||||||
 | 
					 *  the first time that _module_ (which may be a <code>String</code> or
 | 
				
			||||||
 | 
					 *  a symbol) is accessed in the namespace of _mod_.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     module A
 | 
				
			||||||
 | 
					 *     end
 | 
				
			||||||
 | 
					 *     A.autoload(:B, "b")
 | 
				
			||||||
 | 
					 *     A::B.doit            # autoloads "b"
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ID id = rb_to_id(sym);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Check_SafeStr(file);
 | 
				
			||||||
 | 
					    rb_autoload(mod, id, RSTRING_PTR(file));
 | 
				
			||||||
 | 
					    return Qnil;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * MISSING: documentation
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_mod_autoload_p(VALUE mod, VALUE sym)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return rb_autoload_p(mod, rb_to_id(sym));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     autoload(module, filename)   => nil
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Registers _filename_ to be loaded (using <code>Kernel::require</code>)
 | 
				
			||||||
 | 
					 *  the first time that _module_ (which may be a <code>String</code> or
 | 
				
			||||||
 | 
					 *  a symbol) is accessed.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE klass = ruby_cbase();
 | 
				
			||||||
 | 
					    if (NIL_P(klass)) {
 | 
				
			||||||
 | 
						rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return rb_mod_autoload(klass, sym, file);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * MISSING: documentation
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_f_autoload_p(VALUE obj, VALUE sym)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* use ruby_cbase() as same as rb_f_autoload. */
 | 
				
			||||||
 | 
					    VALUE klass = ruby_cbase();
 | 
				
			||||||
 | 
					    if (NIL_P(klass)) {
 | 
				
			||||||
 | 
						return Qnil;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return rb_mod_autoload_p(klass, sym);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					Init_load()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_load_path = rb_ary_new();
 | 
				
			||||||
 | 
					    rb_define_readonly_variable("$:", &rb_load_path);
 | 
				
			||||||
 | 
					    rb_define_readonly_variable("$-I", &rb_load_path);
 | 
				
			||||||
 | 
					    rb_define_readonly_variable("$LOAD_PATH", &rb_load_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_features = rb_ary_new();
 | 
				
			||||||
 | 
					    rb_define_readonly_variable("$\"", &rb_features);
 | 
				
			||||||
 | 
					    rb_define_readonly_variable("$LOADED_FEATURES", &rb_features);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_define_global_function("load", rb_f_load, -1);
 | 
				
			||||||
 | 
					    rb_define_global_function("require", rb_f_require, 1);
 | 
				
			||||||
 | 
					    rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
 | 
				
			||||||
 | 
					    rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
 | 
				
			||||||
 | 
					    rb_define_global_function("autoload", rb_f_autoload, 2);
 | 
				
			||||||
 | 
					    rb_define_global_function("autoload?", rb_f_autoload_p, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ruby_dln_librefs = rb_ary_new();
 | 
				
			||||||
 | 
					    rb_register_mark_object(ruby_dln_librefs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										612
									
								
								eval_method.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										612
									
								
								eval_method.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,612 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is included by eval.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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 */
 | 
				
			||||||
 | 
					    NODE *method;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct cache_entry cache[CACHE_SIZE];
 | 
				
			||||||
 | 
					static int ruby_running = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_clear_cache(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct cache_entry *ent, *end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_vm_change_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!ruby_running)
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					    ent = cache;
 | 
				
			||||||
 | 
					    end = ent + CACHE_SIZE;
 | 
				
			||||||
 | 
					    while (ent < end) {
 | 
				
			||||||
 | 
						ent->mid = 0;
 | 
				
			||||||
 | 
						ent++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					rb_clear_cache_for_undef(VALUE klass, ID id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct cache_entry *ent, *end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_vm_change_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!ruby_running)
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					    ent = cache;
 | 
				
			||||||
 | 
					    end = ent + CACHE_SIZE;
 | 
				
			||||||
 | 
					    while (ent < end) {
 | 
				
			||||||
 | 
						if (ent->method && ent->method->nd_clss == klass && ent->mid == id) {
 | 
				
			||||||
 | 
						    ent->mid = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ent++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					rb_clear_cache_by_id(ID id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct cache_entry *ent, *end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_vm_change_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!ruby_running)
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					    ent = cache;
 | 
				
			||||||
 | 
					    end = ent + CACHE_SIZE;
 | 
				
			||||||
 | 
					    while (ent < end) {
 | 
				
			||||||
 | 
						if (ent->mid == id) {
 | 
				
			||||||
 | 
						    ent->mid = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ent++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_clear_cache_by_class(VALUE klass)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct cache_entry *ent, *end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_vm_change_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!ruby_running)
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					    ent = cache;
 | 
				
			||||||
 | 
					    end = ent + CACHE_SIZE;
 | 
				
			||||||
 | 
					    while (ent < end) {
 | 
				
			||||||
 | 
						if ((ent->klass == klass) ||
 | 
				
			||||||
 | 
						    (ent->method && ent->method->nd_clss == klass)) {
 | 
				
			||||||
 | 
						    ent->mid = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ent++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NODE *body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (NIL_P(klass)) {
 | 
				
			||||||
 | 
						klass = rb_cObject;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (rb_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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
 | 
				
			||||||
 | 
					     *   nd_body : method body   // (2) // mark
 | 
				
			||||||
 | 
					     *   nd_clss : klass         // (1) // mark
 | 
				
			||||||
 | 
					     *   nd_noex : visibility    // (3)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * NODE_FBODY (NEW_FBODY(method, alias)):
 | 
				
			||||||
 | 
					     *   nd_body : method (NODE_METHOD)  // (2) // mark
 | 
				
			||||||
 | 
					     *   nd_oid  : original id           // (1)
 | 
				
			||||||
 | 
					     *   nd_cnt  : alias count           // (3)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (node) {
 | 
				
			||||||
 | 
						body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						body = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
						/* check re-definition */
 | 
				
			||||||
 | 
						NODE *old_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (st_lookup(RCLASS(klass)->m_tbl, mid, (st_data_t *)&old_node)) {
 | 
				
			||||||
 | 
						    if (old_node) {
 | 
				
			||||||
 | 
							if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
 | 
				
			||||||
 | 
							    yarv_check_redefinition_opt_method(old_node);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    if (klass == rb_cObject && node->nd_mid == init) {
 | 
				
			||||||
 | 
							rb_warn("redefining Object#initialize may cause infinite loop");
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    if (RTEST(ruby_verbose) && old_node->nd_cnt == 0 && old_node->nd_body) {
 | 
				
			||||||
 | 
							rb_warning("method redefined; discarding old %s", rb_id2name(mid));
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mid == object_id || mid == __send || mid == __send_bang) {
 | 
				
			||||||
 | 
						    if (node && nd_type(node) == YARV_METHOD_NODE) {
 | 
				
			||||||
 | 
							rb_warn("redefining `%s' may cause serious problem",
 | 
				
			||||||
 | 
								rb_id2name(mid));
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static NODE *
 | 
				
			||||||
 | 
					search_method(VALUE klass, ID id, VALUE *klassp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NODE *body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!klass) {
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (!st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *) & body)) {
 | 
				
			||||||
 | 
						klass = RCLASS(klass)->super;
 | 
				
			||||||
 | 
						if (!klass)
 | 
				
			||||||
 | 
						    return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (klassp) {
 | 
				
			||||||
 | 
						*klassp = klass;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return body;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * search method body (NODE_METHOD)
 | 
				
			||||||
 | 
					 *   with    : klass and id
 | 
				
			||||||
 | 
					 *   without : method cache
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * if you need method node with method cache, use
 | 
				
			||||||
 | 
					 * rb_method_node()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					NODE *
 | 
				
			||||||
 | 
					rb_get_method_body(VALUE klass, ID id, ID *idp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NODE *volatile fbody, *body;
 | 
				
			||||||
 | 
					    NODE *method;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((fbody = search_method(klass, id, 0)) == 0 || !fbody->nd_body) {
 | 
				
			||||||
 | 
						/* store empty info in cache */
 | 
				
			||||||
 | 
						struct cache_entry *ent;
 | 
				
			||||||
 | 
						ent = cache + EXPR1(klass, id);
 | 
				
			||||||
 | 
						ent->klass = klass;
 | 
				
			||||||
 | 
						ent->mid = ent->mid0 = id;
 | 
				
			||||||
 | 
						ent->method = 0;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    method = fbody->nd_body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ruby_running) {
 | 
				
			||||||
 | 
						/* store in cache */
 | 
				
			||||||
 | 
						struct cache_entry *ent;
 | 
				
			||||||
 | 
						ent = cache + EXPR1(klass, id);
 | 
				
			||||||
 | 
						ent->klass = klass;
 | 
				
			||||||
 | 
						ent->mid = id;
 | 
				
			||||||
 | 
						ent->mid0 = fbody->nd_oid;
 | 
				
			||||||
 | 
						ent->method = body = method;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						body = method;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (idp) {
 | 
				
			||||||
 | 
						*idp = fbody->nd_oid;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return body;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NODE *
 | 
				
			||||||
 | 
					rb_method_node(VALUE klass, ID id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct cache_entry *ent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ent = cache + EXPR1(klass, id);
 | 
				
			||||||
 | 
					    if (ent->mid == id && ent->klass == klass && ent->method) {
 | 
				
			||||||
 | 
						return ent->method;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return rb_get_method_body(klass, id, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					remove_method(VALUE klass, ID mid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NODE *body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (klass == rb_cObject) {
 | 
				
			||||||
 | 
						rb_secure(4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (rb_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_undef(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 *fbody;
 | 
				
			||||||
 | 
					    VALUE origin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (klass == rb_cObject) {
 | 
				
			||||||
 | 
						rb_secure(4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fbody = search_method(klass, name, &origin);
 | 
				
			||||||
 | 
					    if (!fbody && TYPE(klass) == T_MODULE) {
 | 
				
			||||||
 | 
						fbody = search_method(rb_cObject, name, &origin);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!fbody || !fbody->nd_body) {
 | 
				
			||||||
 | 
						print_undef(klass, name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (fbody->nd_body->nd_noex != noex) {
 | 
				
			||||||
 | 
						if (klass == origin) {
 | 
				
			||||||
 | 
						    fbody->nd_body->nd_noex = noex;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
						    rb_add_method(klass, name, NEW_ZSUPER(), noex);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					rb_method_boundp(VALUE klass, ID id, int ex)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NODE *method;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((method = rb_method_node(klass, id)) != 0) {
 | 
				
			||||||
 | 
						if (ex && (method->nd_noex & NOEX_PRIVATE)) {
 | 
				
			||||||
 | 
						    return Qfalse;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return Qtrue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return Qfalse;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_attr(VALUE klass, ID id, int read, int write, int ex)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const char *name;
 | 
				
			||||||
 | 
					    char *buf;
 | 
				
			||||||
 | 
					    ID attriv;
 | 
				
			||||||
 | 
					    int noex;
 | 
				
			||||||
 | 
					    size_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!ex) {
 | 
				
			||||||
 | 
						noex = NOEX_PUBLIC;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						if (SCOPE_TEST(NOEX_PRIVATE)) {
 | 
				
			||||||
 | 
						    noex = NOEX_PRIVATE;
 | 
				
			||||||
 | 
						    rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
 | 
				
			||||||
 | 
							       "attribute accessor as module_function" :
 | 
				
			||||||
 | 
							       "private attribute?");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (SCOPE_TEST(NOEX_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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_undef(VALUE klass, ID id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE origin;
 | 
				
			||||||
 | 
					    NODE *body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ruby_cbase() == rb_cObject && klass == rb_cObject) {
 | 
				
			||||||
 | 
						rb_secure(4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (rb_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);
 | 
				
			||||||
 | 
					    if (!body || !body->nd_body) {
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NODE *orig_fbody, *node;
 | 
				
			||||||
 | 
					    VALUE singleton = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_frozen_class_p(klass);
 | 
				
			||||||
 | 
					    if (name == def)
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					    if (klass == rb_cObject) {
 | 
				
			||||||
 | 
						rb_secure(4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    orig_fbody = search_method(klass, def, 0);
 | 
				
			||||||
 | 
					    if (!orig_fbody || !orig_fbody->nd_body) {
 | 
				
			||||||
 | 
						if (TYPE(klass) == T_MODULE) {
 | 
				
			||||||
 | 
						    orig_fbody = search_method(rb_cObject, def, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!orig_fbody || !orig_fbody->nd_body) {
 | 
				
			||||||
 | 
						print_undef(klass, def);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (FL_TEST(klass, FL_SINGLETON)) {
 | 
				
			||||||
 | 
						singleton = rb_iv_get(klass, "__attached__");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    orig_fbody->nd_cnt++;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    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_FBODY(
 | 
				
			||||||
 | 
							  NEW_METHOD(orig_fbody->nd_body->nd_body,
 | 
				
			||||||
 | 
								     orig_fbody->nd_body->nd_clss,
 | 
				
			||||||
 | 
								     orig_fbody->nd_body->nd_noex), def));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_clear_cache_by_id(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1195
									
								
								eval_proc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1195
									
								
								eval_proc.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										117
									
								
								eval_safe.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								eval_safe.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,117 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is included by eval.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 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
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					rb_safe_level(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return GET_THREAD()->safe_level;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_set_safe_level_force(int safe)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    GET_THREAD()->safe_level = safe;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE safe_getter _((void));
 | 
				
			||||||
 | 
					static void safe_setter _((VALUE val));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PROC_TSHIFT (FL_USHIFT+1)
 | 
				
			||||||
 | 
					#define PROC_TMASK  (FL_USER1|FL_USER2|FL_USER3)
 | 
				
			||||||
 | 
					#define PROC_TMAX   (PROC_TMASK >> PROC_TSHIFT)
 | 
				
			||||||
 | 
					#define PROC_NOSAFE FL_USER4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SAFE_LEVEL_MAX PROC_TMASK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* $SAFE accessor */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_set_safe_level(int level)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (level > th->safe_level) {
 | 
				
			||||||
 | 
						if (level > SAFE_LEVEL_MAX) {
 | 
				
			||||||
 | 
						    level = SAFE_LEVEL_MAX;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						th->safe_level = level;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					safe_getter(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return INT2NUM(rb_safe_level());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					safe_setter(VALUE val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int level = NUM2INT(val);
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (level < th->safe_level) {
 | 
				
			||||||
 | 
						rb_raise(rb_eSecurityError,
 | 
				
			||||||
 | 
							 "tried to downgrade safe level from %d to %d",
 | 
				
			||||||
 | 
							 th->safe_level, level);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (level > SAFE_LEVEL_MAX) {
 | 
				
			||||||
 | 
						level = SAFE_LEVEL_MAX;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    th->safe_level = level;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_secure(int level)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (level <= rb_safe_level()) {
 | 
				
			||||||
 | 
						if (rb_frame_callee()) {
 | 
				
			||||||
 | 
						    rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
 | 
				
			||||||
 | 
							     rb_id2name(rb_frame_callee()), rb_safe_level());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
						    rb_raise(rb_eSecurityError, "Insecure operation at level %d",
 | 
				
			||||||
 | 
							     rb_safe_level());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_secure_update(VALUE obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!OBJ_TAINTED(obj))
 | 
				
			||||||
 | 
						rb_secure(4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_check_safe_obj(VALUE x)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (rb_safe_level() > 0 && OBJ_TAINTED(x)) {
 | 
				
			||||||
 | 
						if (rb_frame_callee()) {
 | 
				
			||||||
 | 
						    rb_raise(rb_eSecurityError, "Insecure operation - %s",
 | 
				
			||||||
 | 
							     rb_id2name(rb_frame_callee()));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
						    rb_raise(rb_eSecurityError, "Insecure operation: -r");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rb_secure(4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										683
									
								
								eval_thread.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										683
									
								
								eval_thread.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,683 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Thread from eval.c
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "eval_intern.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __ia64__
 | 
				
			||||||
 | 
					#if defined(__FreeBSD__)
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * FreeBSD/ia64 currently does not have a way for a process to get the
 | 
				
			||||||
 | 
					 * base address for the RSE backing store, so hardcode it.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define __libc_ia64_register_backing_store_base (4ULL<<61)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
 | 
				
			||||||
 | 
					#include <unwind.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#pragma weak __libc_ia64_register_backing_store_base
 | 
				
			||||||
 | 
					extern unsigned long __libc_ia64_register_backing_store_base;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Windows SEH refers data on the stack. */
 | 
				
			||||||
 | 
					#undef SAVE_WIN32_EXCEPTION_LIST
 | 
				
			||||||
 | 
					#if defined _WIN32 || defined __CYGWIN__
 | 
				
			||||||
 | 
					#if defined __CYGWIN__
 | 
				
			||||||
 | 
					typedef unsigned long DWORD;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline DWORD
 | 
				
			||||||
 | 
					win32_get_exception_list()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DWORD p;
 | 
				
			||||||
 | 
					# if defined _MSC_VER
 | 
				
			||||||
 | 
					#   ifdef _M_IX86
 | 
				
			||||||
 | 
					#   define SAVE_WIN32_EXCEPTION_LIST
 | 
				
			||||||
 | 
					#   if _MSC_VER >= 1310
 | 
				
			||||||
 | 
					    /* warning: unsafe assignment to fs:0 ... this is ok */
 | 
				
			||||||
 | 
					#     pragma warning(disable: 4733)
 | 
				
			||||||
 | 
					#   endif
 | 
				
			||||||
 | 
					    __asm mov eax, fs:[0];
 | 
				
			||||||
 | 
					    __asm mov p, eax;
 | 
				
			||||||
 | 
					#   endif
 | 
				
			||||||
 | 
					# elif defined __GNUC__
 | 
				
			||||||
 | 
					#   ifdef __i386__
 | 
				
			||||||
 | 
					#   define SAVE_WIN32_EXCEPTION_LIST
 | 
				
			||||||
 | 
					  __asm__("movl %%fs:0,%0":"=r"(p));
 | 
				
			||||||
 | 
					#   endif
 | 
				
			||||||
 | 
					# elif defined __BORLANDC__
 | 
				
			||||||
 | 
					#   define SAVE_WIN32_EXCEPTION_LIST
 | 
				
			||||||
 | 
					    __emit__(0x64, 0xA1, 0, 0, 0, 0);	/* mov eax, fs:[0] */
 | 
				
			||||||
 | 
					    p = _EAX;
 | 
				
			||||||
 | 
					# endif
 | 
				
			||||||
 | 
					    return p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void
 | 
				
			||||||
 | 
					win32_set_exception_list(p)
 | 
				
			||||||
 | 
					    DWORD p;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					# if defined _MSC_VER
 | 
				
			||||||
 | 
					#   ifdef _M_IX86
 | 
				
			||||||
 | 
					    __asm mov eax, p;
 | 
				
			||||||
 | 
					    __asm mov fs:[0], eax;
 | 
				
			||||||
 | 
					#   endif
 | 
				
			||||||
 | 
					# elif defined __GNUC__
 | 
				
			||||||
 | 
					#   ifdef __i386__
 | 
				
			||||||
 | 
					    __asm__("movl %0,%%fs:0"::"r"(p));
 | 
				
			||||||
 | 
					#   endif
 | 
				
			||||||
 | 
					# elif defined __BORLANDC__
 | 
				
			||||||
 | 
					    _EAX = p;
 | 
				
			||||||
 | 
					    __emit__(0x64, 0xA3, 0, 0, 0, 0);	/* mov fs:[0], eax */
 | 
				
			||||||
 | 
					# endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined SAVE_WIN32_EXCEPTION_LIST && !defined _WIN32_WCE
 | 
				
			||||||
 | 
					# error unsupported platform
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int rb_thread_pending = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE rb_cThread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern VALUE rb_last_status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define WAIT_FD		(1<<0)
 | 
				
			||||||
 | 
					#define WAIT_SELECT	(1<<1)
 | 
				
			||||||
 | 
					#define WAIT_TIME	(1<<2)
 | 
				
			||||||
 | 
					#define WAIT_JOIN	(1<<3)
 | 
				
			||||||
 | 
					#define WAIT_PID	(1<<4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* +infty, for this purpose */
 | 
				
			||||||
 | 
					#define DELAY_INFTY 1E30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef NFDBITS
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_fd_init(fds)
 | 
				
			||||||
 | 
					    volatile rb_fdset_t *fds;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    fds->maxfd = 0;
 | 
				
			||||||
 | 
					    fds->fdset = ALLOC(fd_set);
 | 
				
			||||||
 | 
					    FD_ZERO(fds->fdset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_fd_term(fds)
 | 
				
			||||||
 | 
					    rb_fdset_t *fds;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (fds->fdset)
 | 
				
			||||||
 | 
						free(fds->fdset);
 | 
				
			||||||
 | 
					    fds->maxfd = 0;
 | 
				
			||||||
 | 
					    fds->fdset = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_fd_zero(fds)
 | 
				
			||||||
 | 
					    rb_fdset_t *fds;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (fds->fdset) {
 | 
				
			||||||
 | 
						MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
 | 
				
			||||||
 | 
						FD_ZERO(fds->fdset);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					rb_fd_resize(n, fds)
 | 
				
			||||||
 | 
					    int n;
 | 
				
			||||||
 | 
					    rb_fdset_t *fds;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int m = howmany(n + 1, NFDBITS) * sizeof(fd_mask);
 | 
				
			||||||
 | 
					    int o = howmany(fds->maxfd, NFDBITS) * sizeof(fd_mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m < sizeof(fd_set))
 | 
				
			||||||
 | 
						m = sizeof(fd_set);
 | 
				
			||||||
 | 
					    if (o < sizeof(fd_set))
 | 
				
			||||||
 | 
						o = sizeof(fd_set);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (m > o) {
 | 
				
			||||||
 | 
						fds->fdset = realloc(fds->fdset, m);
 | 
				
			||||||
 | 
						memset((char *)fds->fdset + o, 0, m - o);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (n >= fds->maxfd)
 | 
				
			||||||
 | 
						fds->maxfd = n + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_fd_set(n, fds)
 | 
				
			||||||
 | 
					    int n;
 | 
				
			||||||
 | 
					    rb_fdset_t *fds;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_fd_resize(n, fds);
 | 
				
			||||||
 | 
					    FD_SET(n, fds->fdset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_fd_clr(n, fds)
 | 
				
			||||||
 | 
					    int n;
 | 
				
			||||||
 | 
					    rb_fdset_t *fds;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (n >= fds->maxfd)
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					    FD_CLR(n, fds->fdset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					rb_fd_isset(n, fds)
 | 
				
			||||||
 | 
					    int n;
 | 
				
			||||||
 | 
					    const rb_fdset_t *fds;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (n >= fds->maxfd)
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					    return FD_ISSET(n, fds->fdset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_fd_copy(dst, src, max)
 | 
				
			||||||
 | 
					    rb_fdset_t *dst;
 | 
				
			||||||
 | 
					    const fd_set *src;
 | 
				
			||||||
 | 
					    int max;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int size = howmany(max, NFDBITS) * sizeof(fd_mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (size < sizeof(fd_set))
 | 
				
			||||||
 | 
						size = sizeof(fd_set);
 | 
				
			||||||
 | 
					    dst->maxfd = max;
 | 
				
			||||||
 | 
					    dst->fdset = realloc(dst->fdset, size);
 | 
				
			||||||
 | 
					    memcpy(dst->fdset, src, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					rb_fd_select(n, readfds, writefds, exceptfds, timeout)
 | 
				
			||||||
 | 
					    int n;
 | 
				
			||||||
 | 
					    rb_fdset_t *readfds, *writefds, *exceptfds;
 | 
				
			||||||
 | 
					    struct timeval *timeout;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_fd_resize(n - 1, readfds);
 | 
				
			||||||
 | 
					    rb_fd_resize(n - 1, writefds);
 | 
				
			||||||
 | 
					    rb_fd_resize(n - 1, exceptfds);
 | 
				
			||||||
 | 
					    return select(n, rb_fd_ptr(readfds), rb_fd_ptr(writefds),
 | 
				
			||||||
 | 
							  rb_fd_ptr(exceptfds), timeout);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef FD_ZERO
 | 
				
			||||||
 | 
					#undef FD_SET
 | 
				
			||||||
 | 
					#undef FD_CLR
 | 
				
			||||||
 | 
					#undef FD_ISSET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FD_ZERO(f)	rb_fd_zero(f)
 | 
				
			||||||
 | 
					#define FD_SET(i, f)	rb_fd_set(i, f)
 | 
				
			||||||
 | 
					#define FD_CLR(i, f)	rb_fd_clr(i, f)
 | 
				
			||||||
 | 
					#define FD_ISSET(i, f)	rb_fd_isset(i, f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* typedef struct thread * rb_thread_t; */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct thread {
 | 
				
			||||||
 | 
					    /* obsolete */
 | 
				
			||||||
 | 
					    struct thread *next, *prev;
 | 
				
			||||||
 | 
					    rb_jmpbuf_t context;
 | 
				
			||||||
 | 
					#ifdef SAVE_WIN32_EXCEPTION_LIST
 | 
				
			||||||
 | 
					    DWORD win32_exception_list;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VALUE result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    long stk_len;
 | 
				
			||||||
 | 
					    long stk_max;
 | 
				
			||||||
 | 
					    VALUE *stk_ptr;
 | 
				
			||||||
 | 
					    VALUE *stk_pos;
 | 
				
			||||||
 | 
					#ifdef __ia64__
 | 
				
			||||||
 | 
					    VALUE *bstr_ptr;
 | 
				
			||||||
 | 
					    long bstr_len;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct FRAME *frame;
 | 
				
			||||||
 | 
					    struct SCOPE *scope;
 | 
				
			||||||
 | 
					    struct RVarmap *dyna_vars;
 | 
				
			||||||
 | 
					    struct BLOCK *block;
 | 
				
			||||||
 | 
					    struct iter *iter;
 | 
				
			||||||
 | 
					    struct tag *tag;
 | 
				
			||||||
 | 
					    VALUE klass;
 | 
				
			||||||
 | 
					    VALUE wrapper;
 | 
				
			||||||
 | 
					    NODE *cref;
 | 
				
			||||||
 | 
					    struct ruby_env *anchor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int flags;			/* misc. states (vmode/rb_trap_immediate/raised) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NODE *node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int tracing;
 | 
				
			||||||
 | 
					    VALUE errinfo;
 | 
				
			||||||
 | 
					    VALUE last_status;
 | 
				
			||||||
 | 
					    VALUE last_line;
 | 
				
			||||||
 | 
					    VALUE last_match;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int safe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum yarv_thread_status status;
 | 
				
			||||||
 | 
					    int wait_for;
 | 
				
			||||||
 | 
					    int fd;
 | 
				
			||||||
 | 
					    rb_fdset_t readfds;
 | 
				
			||||||
 | 
					    rb_fdset_t writefds;
 | 
				
			||||||
 | 
					    rb_fdset_t exceptfds;
 | 
				
			||||||
 | 
					    int select_value;
 | 
				
			||||||
 | 
					    double delay;
 | 
				
			||||||
 | 
					    rb_thread_t join;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int abort;
 | 
				
			||||||
 | 
					    int priority;
 | 
				
			||||||
 | 
					    VALUE thgroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    st_table *locals;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VALUE thread;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define THREAD_RAISED 0x200	/* temporary flag */
 | 
				
			||||||
 | 
					#define THREAD_TERMINATING 0x400	/* persistent flag */
 | 
				
			||||||
 | 
					#define THREAD_FLAGS_MASK  0x400	/* mask for persistent flags */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
 | 
				
			||||||
 | 
					#define END_FOREACH_FROM(f,x) } while (x != f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FOREACH_THREAD(x) FOREACH_THREAD_FROM(curr_thread,x)
 | 
				
			||||||
 | 
					#define END_FOREACH(x)    END_FOREACH_FROM(curr_thread,x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct thread_status_t {
 | 
				
			||||||
 | 
					    NODE *node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int tracing;
 | 
				
			||||||
 | 
					    VALUE errinfo;
 | 
				
			||||||
 | 
					    VALUE last_status;
 | 
				
			||||||
 | 
					    VALUE last_line;
 | 
				
			||||||
 | 
					    VALUE last_match;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int safe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum yarv_thread_status status;
 | 
				
			||||||
 | 
					    int wait_for;
 | 
				
			||||||
 | 
					    int fd;
 | 
				
			||||||
 | 
					    rb_fdset_t readfds;
 | 
				
			||||||
 | 
					    rb_fdset_t writefds;
 | 
				
			||||||
 | 
					    rb_fdset_t exceptfds;
 | 
				
			||||||
 | 
					    int select_value;
 | 
				
			||||||
 | 
					    double delay;
 | 
				
			||||||
 | 
					    rb_thread_t join;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define THREAD_COPY_STATUS(src, dst) (void)(	\
 | 
				
			||||||
 | 
					    (dst)->node = (src)->node,			\
 | 
				
			||||||
 | 
											\
 | 
				
			||||||
 | 
					    (dst)->tracing = (src)->tracing,		\
 | 
				
			||||||
 | 
					    (dst)->errinfo = (src)->errinfo,		\
 | 
				
			||||||
 | 
					    (dst)->last_status = (src)->last_status,	\
 | 
				
			||||||
 | 
					    (dst)->last_line = (src)->last_line,	\
 | 
				
			||||||
 | 
					    (dst)->last_match = (src)->last_match,	\
 | 
				
			||||||
 | 
											\
 | 
				
			||||||
 | 
					    (dst)->safe = (src)->safe,			\
 | 
				
			||||||
 | 
											\
 | 
				
			||||||
 | 
					    (dst)->status = (src)->status,		\
 | 
				
			||||||
 | 
					    (dst)->wait_for = (src)->wait_for,		\
 | 
				
			||||||
 | 
					    (dst)->fd = (src)->fd,			\
 | 
				
			||||||
 | 
					    (dst)->readfds = (src)->readfds,		\
 | 
				
			||||||
 | 
					    (dst)->writefds = (src)->writefds,		\
 | 
				
			||||||
 | 
					    (dst)->exceptfds = (src)->exceptfds,	\
 | 
				
			||||||
 | 
					    rb_fd_init(&(src)->readfds),		\
 | 
				
			||||||
 | 
					    rb_fd_init(&(src)->writefds),		\
 | 
				
			||||||
 | 
					    rb_fd_init(&(src)->exceptfds),		\
 | 
				
			||||||
 | 
					    (dst)->select_value = (src)->select_value,	\
 | 
				
			||||||
 | 
					    (dst)->delay = (src)->delay,		\
 | 
				
			||||||
 | 
					    (dst)->join = (src)->join,			\
 | 
				
			||||||
 | 
					    0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					thread_set_raised(yarv_thread_t *th)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (th->raised_flag) {
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    th->raised_flag = 1;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					thread_reset_raised(yarv_thread_t *th)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (th->raised_flag == 0) {
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    th->raised_flag = 0;
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_thread_fd_close(fd)
 | 
				
			||||||
 | 
					    int fd;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // TODO: fix me
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_thread_current()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return GET_THREAD()->self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rb_thread_t
 | 
				
			||||||
 | 
					rb_thread_alloc(klass)
 | 
				
			||||||
 | 
					    VALUE klass;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    UNSUPPORTED(rb_thread_alloc);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_thread_start_0(fn, arg, th)
 | 
				
			||||||
 | 
					    VALUE (*fn) ();
 | 
				
			||||||
 | 
					    void *arg;
 | 
				
			||||||
 | 
					    rb_thread_t th;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_bug("unsupported: rb_thread_start_0");
 | 
				
			||||||
 | 
					    return 0;			/* not reached */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_thread_create(VALUE (*fn) (), void *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Init_stack((VALUE *)&arg);
 | 
				
			||||||
 | 
					    return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     Thread.new([arg]*) {|args| block }   => thread
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Creates and runs a new thread to execute the instructions given in
 | 
				
			||||||
 | 
					 *  <i>block</i>. Any arguments passed to <code>Thread::new</code> are passed
 | 
				
			||||||
 | 
					 *  into the block.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     x = Thread.new { sleep 0.1; print "x"; print "y"; print "z" }
 | 
				
			||||||
 | 
					 *     a = Thread.new { print "a"; print "b"; sleep 0.2; print "c" }
 | 
				
			||||||
 | 
					 *     x.join # Let the threads finish before
 | 
				
			||||||
 | 
					 *     a.join # main thread exits...
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     abxyzc
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     Thread.new([arg]*) {|args| block }   => thread
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Creates and runs a new thread to execute the instructions given in
 | 
				
			||||||
 | 
					 *  <i>block</i>. Any arguments passed to <code>Thread::new</code> are passed
 | 
				
			||||||
 | 
					 *  into the block.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     x = Thread.new { sleep 0.1; print "x"; print "y"; print "z" }
 | 
				
			||||||
 | 
					 *     a = Thread.new { print "a"; print "b"; sleep 0.2; print "c" }
 | 
				
			||||||
 | 
					 *     x.join # Let the threads finish before
 | 
				
			||||||
 | 
					 *     a.join # main thread exits...
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     abxyzc
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     Thread.start([args]*) {|args| block }   => thread
 | 
				
			||||||
 | 
					 *     Thread.fork([args]*) {|args| block }    => thread
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Basically the same as <code>Thread::new</code>. However, if class
 | 
				
			||||||
 | 
					 *  <code>Thread</code> is subclassed, then calling <code>start</code> in that
 | 
				
			||||||
 | 
					 *  subclass will not invoke the subclass's <code>initialize</code> method.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int rb_thread_critical;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     Thread.critical   => true or false
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Returns the status of the global ``thread critical'' condition.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     Thread.critical= boolean   => true or false
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Sets the status of the global ``thread critical'' condition and returns
 | 
				
			||||||
 | 
					 *  it. When set to <code>true</code>, prohibits scheduling of any existing
 | 
				
			||||||
 | 
					 *  thread. Does not block new threads from being created and run. Certain
 | 
				
			||||||
 | 
					 *  thread operations (such as stopping or killing a thread, sleeping in the
 | 
				
			||||||
 | 
					 *  current thread, and raising an exception) may cause a thread to be scheduled
 | 
				
			||||||
 | 
					 *  even when in a critical section.  <code>Thread::critical</code> is not
 | 
				
			||||||
 | 
					 *  intended for daily use: it is primarily there to support folks writing
 | 
				
			||||||
 | 
					 *  threading libraries.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  Document-class: Continuation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Continuation objects are generated by
 | 
				
			||||||
 | 
					 *  <code>Kernel#callcc</code>. They hold a return address and execution
 | 
				
			||||||
 | 
					 *  context, allowing a nonlocal return to the end of the
 | 
				
			||||||
 | 
					 *  <code>callcc</code> block from anywhere within a program.
 | 
				
			||||||
 | 
					 *  Continuations are somewhat analogous to a structured version of C's
 | 
				
			||||||
 | 
					 *  <code>setjmp/longjmp</code> (although they contain more state, so
 | 
				
			||||||
 | 
					 *  you might consider them closer to threads).
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  For instance:
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
 | 
				
			||||||
 | 
					 *     callcc{|$cc|}
 | 
				
			||||||
 | 
					 *     puts(message = arr.shift)
 | 
				
			||||||
 | 
					 *     $cc.call unless message =~ /Max/
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     Freddie
 | 
				
			||||||
 | 
					 *     Herbie
 | 
				
			||||||
 | 
					 *     Ron
 | 
				
			||||||
 | 
					 *     Max
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  This (somewhat contrived) example allows the inner loop to abandon
 | 
				
			||||||
 | 
					 *  processing early:
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     callcc {|cont|
 | 
				
			||||||
 | 
					 *       for i in 0..4
 | 
				
			||||||
 | 
					 *         print "\n#{i}: "
 | 
				
			||||||
 | 
					 *         for j in i*5...(i+1)*5
 | 
				
			||||||
 | 
					 *           cont.call() if j == 17
 | 
				
			||||||
 | 
					 *           printf "%3d", j
 | 
				
			||||||
 | 
					 *         end
 | 
				
			||||||
 | 
					 *       end
 | 
				
			||||||
 | 
					 *     }
 | 
				
			||||||
 | 
					 *     print "\n"
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  <em>produces:</em>
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     0:   0  1  2  3  4
 | 
				
			||||||
 | 
					 *     1:   5  6  7  8  9
 | 
				
			||||||
 | 
					 *     2:  10 11 12 13 14
 | 
				
			||||||
 | 
					 *     3:  15 16
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE rb_cCont;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     callcc {|cont| block }   =>  obj
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Generates a <code>Continuation</code> object, which it passes to the
 | 
				
			||||||
 | 
					 *  associated block. Performing a <em>cont</em><code>.call</code> will
 | 
				
			||||||
 | 
					 *  cause the <code>callcc</code> to return (as will falling through the
 | 
				
			||||||
 | 
					 *  end of the block). The value returned by the <code>callcc</code> is
 | 
				
			||||||
 | 
					 *  the value of the block, or the value passed to
 | 
				
			||||||
 | 
					 *  <em>cont</em><code>.call</code>. See class <code>Continuation</code>
 | 
				
			||||||
 | 
					 *  for more details. Also see <code>Kernel::throw</code> for
 | 
				
			||||||
 | 
					 *  an alternative mechanism for unwinding a call stack.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_callcc(self)
 | 
				
			||||||
 | 
					    VALUE self;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    UNSUPPORTED(rb_callcc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  call-seq:
 | 
				
			||||||
 | 
					 *     cont.call(args, ...)
 | 
				
			||||||
 | 
					 *     cont[args, ...]
 | 
				
			||||||
 | 
					 *  
 | 
				
			||||||
 | 
					 *  Invokes the continuation. The program continues from the end of the
 | 
				
			||||||
 | 
					 *  <code>callcc</code> block. If no arguments are given, the original
 | 
				
			||||||
 | 
					 *  <code>callcc</code> returns <code>nil</code>. If one argument is
 | 
				
			||||||
 | 
					 *  given, <code>callcc</code> returns it. Otherwise, an array
 | 
				
			||||||
 | 
					 *  containing <i>args</i> is returned.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *     callcc {|cont|  cont.call }           #=> nil
 | 
				
			||||||
 | 
					 *     callcc {|cont|  cont.call 1 }         #=> 1
 | 
				
			||||||
 | 
					 *     callcc {|cont|  cont.call 1, 2, 3 }   #=> [1, 2, 3]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_cont_call(argc, argv, cont)
 | 
				
			||||||
 | 
					    int argc;
 | 
				
			||||||
 | 
					    VALUE *argv;
 | 
				
			||||||
 | 
					    VALUE cont;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    UNSUPPORTED(rb_cont_call);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* variables for recursive traversals */
 | 
				
			||||||
 | 
					static ID recursive_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  +Thread+ encapsulates the behavior of a thread of
 | 
				
			||||||
 | 
					 *  execution, including the main thread of the Ruby script.
 | 
				
			||||||
 | 
					 *     
 | 
				
			||||||
 | 
					 *  In the descriptions of the methods in this class, the parameter _sym_
 | 
				
			||||||
 | 
					 *  refers to a symbol, which is either a quoted string or a
 | 
				
			||||||
 | 
					 *  +Symbol+ (such as <code>:name</code>).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					Init_Thread()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    recursive_key = rb_intern("__recursive_key__");
 | 
				
			||||||
 | 
					    rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
 | 
				
			||||||
 | 
					    rb_cCont = rb_define_class("Continuation", rb_cObject);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					recursive_check(obj)
 | 
				
			||||||
 | 
					    VALUE obj;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (NIL_P(hash) || TYPE(hash) != T_HASH) {
 | 
				
			||||||
 | 
						return Qfalse;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						VALUE list = rb_hash_aref(hash, ID2SYM(rb_frame_this_func()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (NIL_P(list) || TYPE(list) != T_ARRAY)
 | 
				
			||||||
 | 
						    return Qfalse;
 | 
				
			||||||
 | 
						return rb_ary_includes(list, rb_obj_id(obj));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					recursive_push(obj)
 | 
				
			||||||
 | 
					    VALUE obj;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
 | 
				
			||||||
 | 
					    VALUE list, sym;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sym = ID2SYM(rb_frame_this_func());
 | 
				
			||||||
 | 
					    if (NIL_P(hash) || TYPE(hash) != T_HASH) {
 | 
				
			||||||
 | 
						hash = rb_hash_new();
 | 
				
			||||||
 | 
						rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
 | 
				
			||||||
 | 
						list = Qnil;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						list = rb_hash_aref(hash, sym);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (NIL_P(list) || TYPE(list) != T_ARRAY) {
 | 
				
			||||||
 | 
						list = rb_ary_new();
 | 
				
			||||||
 | 
						rb_hash_aset(hash, sym, list);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rb_ary_push(list, rb_obj_id(obj));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					recursive_pop()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
 | 
				
			||||||
 | 
					    VALUE list, sym;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sym = ID2SYM(rb_frame_this_func());
 | 
				
			||||||
 | 
					    if (NIL_P(hash) || TYPE(hash) != T_HASH) {
 | 
				
			||||||
 | 
						VALUE symname;
 | 
				
			||||||
 | 
						VALUE thrname;
 | 
				
			||||||
 | 
						symname = rb_inspect(sym);
 | 
				
			||||||
 | 
						thrname = rb_inspect(rb_thread_current());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rb_raise(rb_eTypeError, "invalid inspect_tbl hash for %s in %s",
 | 
				
			||||||
 | 
							 StringValuePtr(symname), StringValuePtr(thrname));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    list = rb_hash_aref(hash, sym);
 | 
				
			||||||
 | 
					    if (NIL_P(list) || TYPE(list) != T_ARRAY) {
 | 
				
			||||||
 | 
						VALUE symname = rb_inspect(sym);
 | 
				
			||||||
 | 
						VALUE thrname = rb_inspect(rb_thread_current());
 | 
				
			||||||
 | 
						rb_raise(rb_eTypeError, "invalid inspect_tbl list for %s in %s",
 | 
				
			||||||
 | 
							 StringValuePtr(symname), StringValuePtr(thrname));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rb_ary_pop(list);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (recursive_check(obj)) {
 | 
				
			||||||
 | 
						return (*func) (obj, arg, Qtrue);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						VALUE result = Qundef;
 | 
				
			||||||
 | 
						int state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						recursive_push(obj);
 | 
				
			||||||
 | 
						PUSH_TAG(PROT_NONE);
 | 
				
			||||||
 | 
						if ((state = EXEC_TAG()) == 0) {
 | 
				
			||||||
 | 
						    result = (*func) (obj, arg, Qfalse);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						POP_TAG();
 | 
				
			||||||
 | 
						recursive_pop();
 | 
				
			||||||
 | 
						if (state)
 | 
				
			||||||
 | 
						    JUMP_TAG(state);
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* flush_register_windows must not be inlined because flushrs doesn't flush
 | 
				
			||||||
 | 
					 * current frame in register stack. */
 | 
				
			||||||
 | 
					#ifdef __ia64__
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					flush_register_windows(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    __asm__("flushrs");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -118,12 +118,12 @@ module DL
 | 
				
			||||||
      f = import_function(symname, ctype, argtype, opt[:call_type])
 | 
					      f = import_function(symname, ctype, argtype, opt[:call_type])
 | 
				
			||||||
      name = symname.gsub(/@.+/,'')
 | 
					      name = symname.gsub(/@.+/,'')
 | 
				
			||||||
      @func_map[name] = f
 | 
					      @func_map[name] = f
 | 
				
			||||||
      define_method(name){|*args,&block| f.call(*args,&block)}
 | 
					      # define_method(name){|*args,&block| f.call(*args,&block)}
 | 
				
			||||||
      #module_eval(<<-EOS)
 | 
					      module_eval(<<-EOS)
 | 
				
			||||||
      #  def #{name}(*args, &block)
 | 
					        def #{name}(*args, &block)
 | 
				
			||||||
      #    @func_map['#{name}'].call(*args,&block)
 | 
					          @func_map['#{name}'].call(*args,&block)
 | 
				
			||||||
      #  end
 | 
					        end
 | 
				
			||||||
      #EOS
 | 
					      EOS
 | 
				
			||||||
      module_function(name)
 | 
					      module_function(name)
 | 
				
			||||||
      f
 | 
					      f
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -142,12 +142,12 @@ module DL
 | 
				
			||||||
        raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
 | 
					        raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
      @func_map[name] = f
 | 
					      @func_map[name] = f
 | 
				
			||||||
      define_method(name){|*args,&block| f.call(*args,&block)}
 | 
					      #define_method(name){|*args,&block| f.call(*args,&block)}
 | 
				
			||||||
      #module_eval(<<-EOS)
 | 
					      module_eval(<<-EOS)
 | 
				
			||||||
      #  def #{name}(*args,&block)
 | 
					        def #{name}(*args,&block)
 | 
				
			||||||
      #    @func_map['#{name}'].call(*args,&block)
 | 
					          @func_map['#{name}'].call(*args,&block)
 | 
				
			||||||
      #  end
 | 
					        end
 | 
				
			||||||
      #EOS
 | 
					      EOS
 | 
				
			||||||
      module_function(name)
 | 
					      module_function(name)
 | 
				
			||||||
      f
 | 
					      f
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,3 @@
 | 
				
			||||||
Makefile
 | 
					Makefile
 | 
				
			||||||
mkmf.log
 | 
					mkmf.log
 | 
				
			||||||
*.def
 | 
					*.def
 | 
				
			||||||
extconf.h
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -512,7 +512,6 @@ Init_etc(void)
 | 
				
			||||||
    rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
 | 
					    rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
 | 
				
			||||||
    rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
 | 
					    rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rb_global_variable(&sPasswd);
 | 
					 | 
				
			||||||
    sPasswd =  rb_struct_define("Passwd",
 | 
					    sPasswd =  rb_struct_define("Passwd",
 | 
				
			||||||
				"name", "passwd", "uid", "gid",
 | 
									"name", "passwd", "uid", "gid",
 | 
				
			||||||
#ifdef HAVE_ST_PW_GECOS
 | 
					#ifdef HAVE_ST_PW_GECOS
 | 
				
			||||||
| 
						 | 
					@ -539,12 +538,15 @@ Init_etc(void)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
				NULL);
 | 
									NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_register_mark_object(sPasswd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_GETGRENT
 | 
					#ifdef HAVE_GETGRENT
 | 
				
			||||||
    rb_global_variable(&sGroup);
 | 
					 | 
				
			||||||
    sGroup = rb_struct_define("Group", "name",
 | 
					    sGroup = rb_struct_define("Group", "name",
 | 
				
			||||||
#ifdef HAVE_ST_GR_PASSWD
 | 
					#ifdef HAVE_ST_GR_PASSWD
 | 
				
			||||||
			      "passwd",
 | 
								      "passwd",
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
			      "gid", "mem", NULL);
 | 
								      "gid", "mem", NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rb_register_mark_object(sGroup);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -302,7 +302,7 @@ iconv_fail(VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, co
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    error = rb_class_new_instance(3, args, error);
 | 
					    error = rb_class_new_instance(3, args, error);
 | 
				
			||||||
    if (!rb_block_given_p()) rb_exc_raise(error);
 | 
					    if (!rb_block_given_p()) rb_exc_raise(error);
 | 
				
			||||||
    ruby_errinfo = error;
 | 
					    rb_set_errinfo(error);
 | 
				
			||||||
    return rb_yield(failed);
 | 
					    return rb_yield(failed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,6 @@ static char **readline_attempted_completion_function(const char *text,
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
readline_event()
 | 
					readline_event()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CHECK_INTS;
 | 
					 | 
				
			||||||
    rb_thread_schedule();
 | 
					    rb_thread_schedule();
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,9 @@ require 'mkmf'
 | 
				
			||||||
require 'rbconfig'
 | 
					require 'rbconfig'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main
 | 
					def main
 | 
				
			||||||
 | 
					  Logging.message "YARV doesn't support Ripper"
 | 
				
			||||||
 | 
					  return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  unless find_executable('bison')
 | 
					  unless find_executable('bison')
 | 
				
			||||||
    unless File.exist?('ripper.c') or File.exist?("#{$srcdir}/ripper.c")
 | 
					    unless File.exist?('ripper.c') or File.exist?("#{$srcdir}/ripper.c")
 | 
				
			||||||
      Logging.message 'missing bison; abort'
 | 
					      Logging.message 'missing bison; abort'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1801,7 +1801,7 @@ fole_s_connect(int argc, VALUE *argv, VALUE self)
 | 
				
			||||||
    ole_initialize();
 | 
					    ole_initialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rb_scan_args(argc, argv, "1*", &svr_name, &others);
 | 
					    rb_scan_args(argc, argv, "1*", &svr_name, &others);
 | 
				
			||||||
    if (ruby_safe_level > 0 && OBJ_TAINTED(svr_name)) {
 | 
					    if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
 | 
				
			||||||
        rb_raise(rb_eSecurityError, "Insecure Object Connection - %s",
 | 
					        rb_raise(rb_eSecurityError, "Insecure Object Connection - %s",
 | 
				
			||||||
                 StringValuePtr(svr_name));
 | 
					                 StringValuePtr(svr_name));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -2182,12 +2182,12 @@ fole_initialize(int argc, VALUE *argv, VALUE self)
 | 
				
			||||||
    rb_call_super(0, 0);
 | 
					    rb_call_super(0, 0);
 | 
				
			||||||
    rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);
 | 
					    rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ruby_safe_level > 0 && OBJ_TAINTED(svr_name)) {
 | 
					    if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
 | 
				
			||||||
        rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
 | 
					        rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
 | 
				
			||||||
                 StringValuePtr(svr_name));
 | 
					                 StringValuePtr(svr_name));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!NIL_P(host)) {
 | 
					    if (!NIL_P(host)) {
 | 
				
			||||||
        if (ruby_safe_level > 0 && OBJ_TAINTED(host)) {
 | 
					        if (rb_safe_level() > 0 && OBJ_TAINTED(host)) {
 | 
				
			||||||
            rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
 | 
					            rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
 | 
				
			||||||
                     StringValuePtr(svr_name));
 | 
					                     StringValuePtr(svr_name));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -6645,7 +6645,7 @@ fev_initialize(int argc, VALUE *argv, VALUE self)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(TYPE(itf) != T_NIL) {
 | 
					    if(TYPE(itf) != T_NIL) {
 | 
				
			||||||
        if (ruby_safe_level > 0 && OBJ_TAINTED(itf)) {
 | 
					        if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) {
 | 
				
			||||||
            rb_raise(rb_eSecurityError, "Insecure Event Creation - %s",
 | 
					            rb_raise(rb_eSecurityError, "Insecure Event Creation - %s",
 | 
				
			||||||
                     StringValuePtr(itf));
 | 
					                     StringValuePtr(itf));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -6854,8 +6854,8 @@ folevariant_value(VALUE self)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
Init_win32ole()
 | 
					Init_win32ole()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    rb_global_variable(&ary_ole_event);
 | 
					 | 
				
			||||||
    ary_ole_event = rb_ary_new();
 | 
					    ary_ole_event = rb_ary_new();
 | 
				
			||||||
 | 
					    rb_register_mark_object(ary_ole_event);
 | 
				
			||||||
    id_events = rb_intern("events");
 | 
					    id_events = rb_intern("events");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    com_vtbl.QueryInterface = QueryInterface;
 | 
					    com_vtbl.QueryInterface = QueryInterface;
 | 
				
			||||||
| 
						 | 
					@ -6865,8 +6865,8 @@ Init_win32ole()
 | 
				
			||||||
    com_vtbl.GetTypeInfo = GetTypeInfo;
 | 
					    com_vtbl.GetTypeInfo = GetTypeInfo;
 | 
				
			||||||
    com_vtbl.GetIDsOfNames = GetIDsOfNames;
 | 
					    com_vtbl.GetIDsOfNames = GetIDsOfNames;
 | 
				
			||||||
    com_vtbl.Invoke = Invoke;
 | 
					    com_vtbl.Invoke = Invoke;
 | 
				
			||||||
    rb_global_variable(&com_hash);
 | 
					 | 
				
			||||||
    com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
 | 
					    com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
 | 
				
			||||||
 | 
					    rb_register_mark_object(com_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
 | 
					    cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1759,7 +1759,7 @@ gzfile_read_raw_rescue(VALUE arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct gzfile *gz = (struct gzfile*)arg;
 | 
					    struct gzfile *gz = (struct gzfile*)arg;
 | 
				
			||||||
    VALUE str = Qnil;
 | 
					    VALUE str = Qnil;
 | 
				
			||||||
    if (rb_obj_is_kind_of(ruby_errinfo, rb_eNoMethodError)) {
 | 
					    if (rb_obj_is_kind_of(ruby_errinfo(), rb_eNoMethodError)) {
 | 
				
			||||||
        str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
 | 
					        str = rb_funcall(gz->io, id_read, 1, INT2FIX(GZFILE_READ_SIZE));
 | 
				
			||||||
        if (!NIL_P(str)) {
 | 
					        if (!NIL_P(str)) {
 | 
				
			||||||
            Check_Type(str, T_STRING);
 | 
					            Check_Type(str, T_STRING);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										547
									
								
								gc.c
									
										
									
									
									
								
							
							
						
						
									
										547
									
								
								gc.c
									
										
									
									
									
								
							| 
						 | 
					@ -16,8 +16,8 @@
 | 
				
			||||||
#include "rubysig.h"
 | 
					#include "rubysig.h"
 | 
				
			||||||
#include "st.h"
 | 
					#include "st.h"
 | 
				
			||||||
#include "node.h"
 | 
					#include "node.h"
 | 
				
			||||||
#include "env.h"
 | 
					 | 
				
			||||||
#include "re.h"
 | 
					#include "re.h"
 | 
				
			||||||
 | 
					#include "yarvcore.h"
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <setjmp.h>
 | 
					#include <setjmp.h>
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,9 @@ int rb_io_fptr_finalize(struct OpenFile*);
 | 
				
			||||||
# ifdef HAVE_ALLOCA_H
 | 
					# ifdef HAVE_ALLOCA_H
 | 
				
			||||||
#  include <alloca.h>
 | 
					#  include <alloca.h>
 | 
				
			||||||
# else
 | 
					# else
 | 
				
			||||||
#  ifndef _AIX
 | 
					#  ifdef _AIX
 | 
				
			||||||
 | 
					 #pragma alloca
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
#   ifndef alloca /* predefined by HP cc +Olibcalls */
 | 
					#   ifndef alloca /* predefined by HP cc +Olibcalls */
 | 
				
			||||||
void *alloca ();
 | 
					void *alloca ();
 | 
				
			||||||
#   endif
 | 
					#   endif
 | 
				
			||||||
| 
						 | 
					@ -69,15 +71,115 @@ void *alloca ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned long malloc_increase = 0;
 | 
					static unsigned long malloc_increase = 0;
 | 
				
			||||||
static unsigned long malloc_limit = GC_MALLOC_LIMIT;
 | 
					static unsigned long malloc_limit = GC_MALLOC_LIMIT;
 | 
				
			||||||
static void run_final(VALUE obj);
 | 
					 | 
				
			||||||
static VALUE nomem_error;
 | 
					static VALUE nomem_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dont_gc;
 | 
				
			||||||
 | 
					static int during_gc;
 | 
				
			||||||
 | 
					static int need_call_final = 0;
 | 
				
			||||||
 | 
					static st_table *finalizer_table = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MARK_STACK_MAX 1024
 | 
				
			||||||
 | 
					static VALUE mark_stack[MARK_STACK_MAX];
 | 
				
			||||||
 | 
					static VALUE *mark_stack_ptr;
 | 
				
			||||||
 | 
					static int mark_stack_overflow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef GC_DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
 | 
				
			||||||
 | 
					#pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct RVALUE {
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
						    unsigned long flags;	/* always 0 for freed obj */
 | 
				
			||||||
 | 
						    struct RVALUE *next;
 | 
				
			||||||
 | 
						} free;
 | 
				
			||||||
 | 
						struct RBasic  basic;
 | 
				
			||||||
 | 
						struct RObject object;
 | 
				
			||||||
 | 
						struct RClass  klass;
 | 
				
			||||||
 | 
						struct RFloat  flonum;
 | 
				
			||||||
 | 
						struct RString string;
 | 
				
			||||||
 | 
						struct RArray  array;
 | 
				
			||||||
 | 
						struct RRegexp regexp;
 | 
				
			||||||
 | 
						struct RHash   hash;
 | 
				
			||||||
 | 
						struct RData   data;
 | 
				
			||||||
 | 
						struct RStruct rstruct;
 | 
				
			||||||
 | 
						struct RBignum bignum;
 | 
				
			||||||
 | 
						struct RFile   file;
 | 
				
			||||||
 | 
						struct RNode   node;
 | 
				
			||||||
 | 
						struct RMatch  match;
 | 
				
			||||||
 | 
					    } as;
 | 
				
			||||||
 | 
					#ifdef GC_DEBUG
 | 
				
			||||||
 | 
					    char *file;
 | 
				
			||||||
 | 
					    int   line;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					} RVALUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
 | 
				
			||||||
 | 
					#pragma pack(pop)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static RVALUE *freelist = 0;
 | 
				
			||||||
 | 
					static RVALUE *deferred_final_list = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HEAPS_INCREMENT 10
 | 
				
			||||||
 | 
					static struct heaps_slot {
 | 
				
			||||||
 | 
					    void *membase;
 | 
				
			||||||
 | 
					    RVALUE *slot;
 | 
				
			||||||
 | 
					    int limit;
 | 
				
			||||||
 | 
					} *heaps;
 | 
				
			||||||
 | 
					static int heaps_length = 0;
 | 
				
			||||||
 | 
					static int heaps_used   = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HEAP_MIN_SLOTS 10000
 | 
				
			||||||
 | 
					static int heap_slots = HEAP_MIN_SLOTS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FREE_MIN  4096
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static RVALUE *himem, *lomem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern st_table *rb_class_tbl;
 | 
				
			||||||
 | 
					VALUE *rb_gc_stack_start = 0;
 | 
				
			||||||
 | 
					#ifdef __ia64
 | 
				
			||||||
 | 
					VALUE *rb_gc_register_stack_start = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int gc_stress = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DJGPP
 | 
				
			||||||
 | 
					/* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
 | 
				
			||||||
 | 
					unsigned int _stklen = 0x180000; /* 1.5 kB */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(DJGPP) || defined(_WIN32_WCE)
 | 
				
			||||||
 | 
					static unsigned int STACK_LEVEL_MAX = 65535;
 | 
				
			||||||
 | 
					#elif defined(__human68k__)
 | 
				
			||||||
 | 
					unsigned int _stacksize = 262144;
 | 
				
			||||||
 | 
					# define STACK_LEVEL_MAX (_stacksize - 4096)
 | 
				
			||||||
 | 
					# undef HAVE_GETRLIMIT
 | 
				
			||||||
 | 
					#elif defined(HAVE_GETRLIMIT) || defined(_WIN32)
 | 
				
			||||||
 | 
					static unsigned int STACK_LEVEL_MAX = 655300;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					# define STACK_LEVEL_MAX 655300
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void run_final(VALUE obj);
 | 
				
			||||||
static int garbage_collect(void);
 | 
					static int garbage_collect(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_global_variable(VALUE *var)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rb_gc_register_address(var);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
rb_memerror(void)
 | 
					rb_memerror(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static int recurse = 0;
 | 
					  static int recurse = 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!nomem_error || (recurse > 0 && rb_safe_level() < 4)) {
 | 
					    if (!nomem_error || (recurse > 0 && rb_safe_level() < 4)) {
 | 
				
			||||||
	fprintf(stderr, "[FATAL] failed to allocate memory\n");
 | 
						fprintf(stderr, "[FATAL] failed to allocate memory\n");
 | 
				
			||||||
	exit(1);
 | 
						exit(1);
 | 
				
			||||||
| 
						 | 
					@ -86,8 +188,6 @@ rb_memerror(void)
 | 
				
			||||||
    rb_exc_raise(nomem_error);
 | 
					    rb_exc_raise(nomem_error);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int gc_stress = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  call-seq:
 | 
					 *  call-seq:
 | 
				
			||||||
 *    GC.stress                 => true or false
 | 
					 *    GC.stress                 => true or false
 | 
				
			||||||
| 
						 | 
					@ -211,11 +311,6 @@ ruby_xfree(void *x)
 | 
				
			||||||
	RUBY_CRITICAL(free(x));
 | 
						RUBY_CRITICAL(free(x));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dont_gc;
 | 
					 | 
				
			||||||
static int during_gc;
 | 
					 | 
				
			||||||
static int need_call_final = 0;
 | 
					 | 
				
			||||||
static st_table *finalizer_table = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  call-seq:
 | 
					 *  call-seq:
 | 
				
			||||||
| 
						 | 
					@ -278,6 +373,13 @@ rb_gc_register_address(VALUE *addr)
 | 
				
			||||||
    global_List = tmp;
 | 
					    global_List = tmp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rb_register_mark_object(VALUE obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    VALUE ary = GET_THREAD()->vm->mark_object_ary;
 | 
				
			||||||
 | 
					    rb_ary_push(ary, obj);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
rb_gc_unregister_address(VALUE *addr)
 | 
					rb_gc_unregister_address(VALUE *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -300,70 +402,6 @@ rb_gc_unregister_address(VALUE *addr)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#undef GC_DEBUG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
rb_global_variable(VALUE *var)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    rb_gc_register_address(var);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
 | 
					 | 
				
			||||||
#pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct RVALUE {
 | 
					 | 
				
			||||||
    union {
 | 
					 | 
				
			||||||
	struct {
 | 
					 | 
				
			||||||
	    unsigned long flags;	/* always 0 for freed obj */
 | 
					 | 
				
			||||||
	    struct RVALUE *next;
 | 
					 | 
				
			||||||
	} free;
 | 
					 | 
				
			||||||
	struct RBasic  basic;
 | 
					 | 
				
			||||||
	struct RObject object;
 | 
					 | 
				
			||||||
	struct RClass  klass;
 | 
					 | 
				
			||||||
	struct RFloat  flonum;
 | 
					 | 
				
			||||||
	struct RString string;
 | 
					 | 
				
			||||||
	struct RArray  array;
 | 
					 | 
				
			||||||
	struct RRegexp regexp;
 | 
					 | 
				
			||||||
	struct RHash   hash;
 | 
					 | 
				
			||||||
	struct RData   data;
 | 
					 | 
				
			||||||
	struct RStruct rstruct;
 | 
					 | 
				
			||||||
	struct RBignum bignum;
 | 
					 | 
				
			||||||
	struct RFile   file;
 | 
					 | 
				
			||||||
	struct RNode   node;
 | 
					 | 
				
			||||||
	struct RMatch  match;
 | 
					 | 
				
			||||||
	struct RVarmap varmap;
 | 
					 | 
				
			||||||
	struct SCOPE   scope;
 | 
					 | 
				
			||||||
    } as;
 | 
					 | 
				
			||||||
#ifdef GC_DEBUG
 | 
					 | 
				
			||||||
    char *file;
 | 
					 | 
				
			||||||
    int   line;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
} RVALUE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
 | 
					 | 
				
			||||||
#pragma pack(pop)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static RVALUE *freelist = 0;
 | 
					 | 
				
			||||||
static RVALUE *deferred_final_list = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define HEAPS_INCREMENT 10
 | 
					 | 
				
			||||||
static struct heaps_slot {
 | 
					 | 
				
			||||||
    void *membase;
 | 
					 | 
				
			||||||
    RVALUE *slot;
 | 
					 | 
				
			||||||
    int limit;
 | 
					 | 
				
			||||||
} *heaps;
 | 
					 | 
				
			||||||
static int heaps_length = 0;
 | 
					 | 
				
			||||||
static int heaps_used   = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define HEAP_MIN_SLOTS 10000
 | 
					 | 
				
			||||||
static int heap_slots = HEAP_MIN_SLOTS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define FREE_MIN  4096
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static RVALUE *himem, *lomem;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
add_heap(void)
 | 
					add_heap(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -396,13 +434,13 @@ add_heap(void)
 | 
				
			||||||
	    heap_slots = HEAP_MIN_SLOTS;
 | 
						    heap_slots = HEAP_MIN_SLOTS;
 | 
				
			||||||
	    continue;
 | 
						    continue;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
        heaps[heaps_used].membase = p;
 | 
						heaps[heaps_used].membase = p;
 | 
				
			||||||
        if ((VALUE)p % sizeof(RVALUE) == 0)
 | 
						if ((VALUE)p % sizeof(RVALUE) == 0)
 | 
				
			||||||
            heap_slots += 1;
 | 
						  heap_slots += 1;
 | 
				
			||||||
        else
 | 
						else
 | 
				
			||||||
            p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
 | 
						  p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
 | 
				
			||||||
        heaps[heaps_used].slot = p;
 | 
						heaps[heaps_used].slot = p;
 | 
				
			||||||
        heaps[heaps_used].limit = heap_slots;
 | 
						heaps[heaps_used].limit = heap_slots;
 | 
				
			||||||
	break;
 | 
						break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pend = p + heap_slots;
 | 
					    pend = p + heap_slots;
 | 
				
			||||||
| 
						 | 
					@ -410,7 +448,6 @@ add_heap(void)
 | 
				
			||||||
    if (himem < pend) himem = pend;
 | 
					    if (himem < pend) himem = pend;
 | 
				
			||||||
    heaps_used++;
 | 
					    heaps_used++;
 | 
				
			||||||
    heap_slots *= 1.8;
 | 
					    heap_slots *= 1.8;
 | 
				
			||||||
    if (heap_slots <= 0) heap_slots = HEAP_MIN_SLOTS;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (p < pend) {
 | 
					    while (p < pend) {
 | 
				
			||||||
	p->as.free.flags = 0;
 | 
						p->as.free.flags = 0;
 | 
				
			||||||
| 
						 | 
					@ -421,16 +458,20 @@ add_heap(void)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#define RANY(o) ((RVALUE*)(o))
 | 
					#define RANY(o) ((RVALUE*)(o))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VALUE
 | 
					static VALUE
 | 
				
			||||||
rb_newobj(void)
 | 
					rb_newobj_from_heap(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VALUE obj;
 | 
					    VALUE obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((gc_stress || !freelist) && !garbage_collect())
 | 
					    if (gc_stress || !freelist) {
 | 
				
			||||||
	rb_memerror();
 | 
						if(!garbage_collect()) {
 | 
				
			||||||
 | 
						    rb_memerror();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    obj = (VALUE)freelist;
 | 
					    obj = (VALUE)freelist;
 | 
				
			||||||
    freelist = freelist->as.free.next;
 | 
					    freelist = freelist->as.free.next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MEMZERO((void*)obj, RVALUE, 1);
 | 
					    MEMZERO((void*)obj, RVALUE, 1);
 | 
				
			||||||
#ifdef GC_DEBUG
 | 
					#ifdef GC_DEBUG
 | 
				
			||||||
    RANY(obj)->file = ruby_sourcefile;
 | 
					    RANY(obj)->file = ruby_sourcefile;
 | 
				
			||||||
| 
						 | 
					@ -439,6 +480,52 @@ rb_newobj(void)
 | 
				
			||||||
    return obj;
 | 
					    return obj;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_VALUE_CACHE
 | 
				
			||||||
 | 
					static VALUE
 | 
				
			||||||
 | 
					rb_fill_value_cache(yarv_thread_t *th)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					    VALUE rv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // LOCK
 | 
				
			||||||
 | 
					    for (i=0; i<YARV_VALUE_CACHE_SIZE; i++) {
 | 
				
			||||||
 | 
						VALUE v = rb_newobj_from_heap();
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						th->value_cache[i] = v;
 | 
				
			||||||
 | 
						RBASIC(v)->flags = FL_MARK;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    th->value_cache_ptr = &th->value_cache[0];
 | 
				
			||||||
 | 
					    rv = rb_newobj_from_heap();
 | 
				
			||||||
 | 
					    // UNLOCK
 | 
				
			||||||
 | 
					    return rv;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VALUE
 | 
				
			||||||
 | 
					rb_newobj(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if USE_VALUE_CACHE && 1
 | 
				
			||||||
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					    VALUE v = *th->value_cache_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (v) {
 | 
				
			||||||
 | 
						RBASIC(v)->flags = 0;
 | 
				
			||||||
 | 
						th->value_cache_ptr++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						v = rb_fill_value_cache(th);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(GC_DEBUG)
 | 
				
			||||||
 | 
					    printf("cache index: %d, v: %p, th: %p\n",
 | 
				
			||||||
 | 
						   th->value_cache_ptr - th->value_cache, v, th);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    return v;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    return rb_newobj_from_heap();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VALUE
 | 
					VALUE
 | 
				
			||||||
rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
 | 
					rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -452,50 +539,21 @@ rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_F
 | 
				
			||||||
    return (VALUE)data;
 | 
					    return (VALUE)data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern st_table *rb_class_tbl;
 | 
					NOINLINE(void yarv_set_stack_end(VALUE **stack_end_p));
 | 
				
			||||||
VALUE *rb_gc_stack_start = 0;
 | 
					 | 
				
			||||||
#ifdef __ia64
 | 
					 | 
				
			||||||
VALUE *rb_gc_register_stack_start = 0;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define YARV_SET_STACK_END yarv_set_stack_end(&th->machine_stack_end)
 | 
				
			||||||
#ifdef DJGPP
 | 
					#define STACK_START (th->machine_stack_start)
 | 
				
			||||||
/* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
 | 
					#define STACK_END (th->machine_stack_end)
 | 
				
			||||||
unsigned int _stklen = 0x180000; /* 1.5 kB */
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(DJGPP) || defined(_WIN32_WCE)
 | 
					 | 
				
			||||||
static unsigned int STACK_LEVEL_MAX = 65535;
 | 
					 | 
				
			||||||
#elif defined(__human68k__)
 | 
					 | 
				
			||||||
unsigned int _stacksize = 262144;
 | 
					 | 
				
			||||||
# define STACK_LEVEL_MAX (_stacksize - 4096)
 | 
					 | 
				
			||||||
# undef HAVE_GETRLIMIT
 | 
					 | 
				
			||||||
#elif defined(HAVE_GETRLIMIT) || defined(_WIN32)
 | 
					 | 
				
			||||||
static unsigned int STACK_LEVEL_MAX = 655300;
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
# define STACK_LEVEL_MAX 655300
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOINLINE(static void set_stack_end(VALUE **stack_end_p));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
set_stack_end(VALUE **stack_end_p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    VALUE stack_end;
 | 
					 | 
				
			||||||
    *stack_end_p = &stack_end;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#define SET_STACK_END    VALUE *stack_end; set_stack_end(&stack_end)
 | 
					 | 
				
			||||||
#define STACK_END        (stack_end)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(sparc) || defined(__sparc__)
 | 
					#if defined(sparc) || defined(__sparc__)
 | 
				
			||||||
# define STACK_LENGTH  (rb_gc_stack_start - STACK_END + 0x80)
 | 
					# define STACK_LENGTH  (STACK_START - STACK_END + 0x80)
 | 
				
			||||||
#elif STACK_GROW_DIRECTION < 0
 | 
					#elif STACK_GROW_DIRECTION < 0
 | 
				
			||||||
# define STACK_LENGTH  (rb_gc_stack_start - STACK_END)
 | 
					# define STACK_LENGTH  (STACK_START - STACK_END)
 | 
				
			||||||
#elif STACK_GROW_DIRECTION > 0
 | 
					#elif STACK_GROW_DIRECTION > 0
 | 
				
			||||||
# define STACK_LENGTH  (STACK_END - rb_gc_stack_start + 1)
 | 
					# define STACK_LENGTH  (STACK_END - STACK_START + 1)
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
# define STACK_LENGTH  ((STACK_END < rb_gc_stack_start) ? rb_gc_stack_start - STACK_END\
 | 
					# define STACK_LENGTH  ((STACK_END < STACK_START) ? STACK_START - STACK_END\
 | 
				
			||||||
                                           : STACK_END - rb_gc_stack_start + 1)
 | 
					                                           : STACK_END - STACK_START + 1)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#if STACK_GROW_DIRECTION > 0
 | 
					#if STACK_GROW_DIRECTION > 0
 | 
				
			||||||
# define STACK_UPPER(x, a, b) a
 | 
					# define STACK_UPPER(x, a, b) a
 | 
				
			||||||
| 
						 | 
					@ -506,10 +564,11 @@ static int grow_direction;
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
stack_grow_direction(VALUE *addr)
 | 
					stack_grow_direction(VALUE *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SET_STACK_END;
 | 
					  yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					  YARV_SET_STACK_END;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (STACK_END > addr) return grow_direction = 1;
 | 
					  if (STACK_END > addr) return grow_direction = 1;
 | 
				
			||||||
    return grow_direction = -1;
 | 
					  return grow_direction = -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
# define stack_growup_p(x) ((grow_direction ? grow_direction : stack_grow_direction(x)) > 0)
 | 
					# define stack_growup_p(x) ((grow_direction ? grow_direction : stack_grow_direction(x)) > 0)
 | 
				
			||||||
# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? a : b)
 | 
					# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? a : b)
 | 
				
			||||||
| 
						 | 
					@ -518,32 +577,28 @@ stack_grow_direction(VALUE *addr)
 | 
				
			||||||
#define GC_WATER_MARK 512
 | 
					#define GC_WATER_MARK 512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHECK_STACK(ret) do {\
 | 
					#define CHECK_STACK(ret) do {\
 | 
				
			||||||
    SET_STACK_END;\
 | 
					    YARV_SET_STACK_END;\
 | 
				
			||||||
    (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
 | 
					    (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
 | 
				
			||||||
} while (0)
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
ruby_stack_length(VALUE **p)
 | 
					ruby_stack_length(VALUE **p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SET_STACK_END;
 | 
					  yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
    if (p) *p = STACK_UPPER(STACK_END, rb_gc_stack_start, STACK_END);
 | 
					  YARV_SET_STACK_END;
 | 
				
			||||||
    return STACK_LENGTH;
 | 
					  if (p) *p = STACK_UPPER(STACK_END, STACK_START, STACK_END);
 | 
				
			||||||
 | 
					  return STACK_LENGTH;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
ruby_stack_check(void)
 | 
					ruby_stack_check(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret;
 | 
					  int ret;
 | 
				
			||||||
 | 
					  yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
    CHECK_STACK(ret);
 | 
					  CHECK_STACK(ret);
 | 
				
			||||||
    return ret;
 | 
					  return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MARK_STACK_MAX 1024
 | 
					 | 
				
			||||||
static VALUE mark_stack[MARK_STACK_MAX];
 | 
					 | 
				
			||||||
static VALUE *mark_stack_ptr;
 | 
					 | 
				
			||||||
static int mark_stack_overflow;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
init_mark_stack(void)
 | 
					init_mark_stack(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -624,7 +679,7 @@ gc_mark_rest(void)
 | 
				
			||||||
    MEMCPY(tmp_arry, mark_stack, VALUE, MARK_STACK_MAX);
 | 
					    MEMCPY(tmp_arry, mark_stack, VALUE, MARK_STACK_MAX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init_mark_stack();
 | 
					    init_mark_stack();
 | 
				
			||||||
    while (p != tmp_arry){
 | 
					    while(p != tmp_arry){
 | 
				
			||||||
	p--;
 | 
						p--;
 | 
				
			||||||
	gc_mark_children(*p, 0);
 | 
						gc_mark_children(*p, 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -644,7 +699,7 @@ is_pointer_to_heap(void *ptr)
 | 
				
			||||||
    for (i=0; i < heaps_used; i++) {
 | 
					    for (i=0; i < heaps_used; i++) {
 | 
				
			||||||
	heap_org = heaps[i].slot;
 | 
						heap_org = heaps[i].slot;
 | 
				
			||||||
	if (heap_org <= p && p < heap_org + heaps[i].limit)
 | 
						if (heap_org <= p && p < heap_org + heaps[i].limit)
 | 
				
			||||||
	    return Qtrue;
 | 
						  return Qtrue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return Qfalse;
 | 
					    return Qfalse;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -785,6 +840,7 @@ gc_mark_children(VALUE ptr, int lev)
 | 
				
			||||||
	  case NODE_IF:		/* 1,2,3 */
 | 
						  case NODE_IF:		/* 1,2,3 */
 | 
				
			||||||
	  case NODE_FOR:
 | 
						  case NODE_FOR:
 | 
				
			||||||
	  case NODE_ITER:
 | 
						  case NODE_ITER:
 | 
				
			||||||
 | 
						  case NODE_CREF:
 | 
				
			||||||
	  case NODE_WHEN:
 | 
						  case NODE_WHEN:
 | 
				
			||||||
	  case NODE_MASGN:
 | 
						  case NODE_MASGN:
 | 
				
			||||||
	  case NODE_RESCUE:
 | 
						  case NODE_RESCUE:
 | 
				
			||||||
| 
						 | 
					@ -795,17 +851,16 @@ gc_mark_children(VALUE ptr, int lev)
 | 
				
			||||||
	    gc_mark((VALUE)obj->as.node.u2.node, lev);
 | 
						    gc_mark((VALUE)obj->as.node.u2.node, lev);
 | 
				
			||||||
	    /* fall through */
 | 
						    /* fall through */
 | 
				
			||||||
	  case NODE_BLOCK:	/* 1,3 */
 | 
						  case NODE_BLOCK:	/* 1,3 */
 | 
				
			||||||
 | 
						  case NODE_OPTBLOCK:
 | 
				
			||||||
	  case NODE_ARRAY:
 | 
						  case NODE_ARRAY:
 | 
				
			||||||
	  case NODE_DSTR:
 | 
						  case NODE_DSTR:
 | 
				
			||||||
	  case NODE_DXSTR:
 | 
						  case NODE_DXSTR:
 | 
				
			||||||
	  case NODE_DREGX:
 | 
						  case NODE_DREGX:
 | 
				
			||||||
	  case NODE_DREGX_ONCE:
 | 
						  case NODE_DREGX_ONCE:
 | 
				
			||||||
	  case NODE_FBODY:
 | 
					 | 
				
			||||||
	  case NODE_ENSURE:
 | 
						  case NODE_ENSURE:
 | 
				
			||||||
	  case NODE_CALL:
 | 
						  case NODE_CALL:
 | 
				
			||||||
	  case NODE_DEFS:
 | 
						  case NODE_DEFS:
 | 
				
			||||||
	  case NODE_OP_ASGN1:
 | 
						  case NODE_OP_ASGN1:
 | 
				
			||||||
	  case NODE_CREF:
 | 
					 | 
				
			||||||
	    gc_mark((VALUE)obj->as.node.u1.node, lev);
 | 
						    gc_mark((VALUE)obj->as.node.u1.node, lev);
 | 
				
			||||||
	    /* fall through */
 | 
						    /* fall through */
 | 
				
			||||||
	  case NODE_SUPER:	/* 3 */
 | 
						  case NODE_SUPER:	/* 3 */
 | 
				
			||||||
| 
						 | 
					@ -814,7 +869,8 @@ gc_mark_children(VALUE ptr, int lev)
 | 
				
			||||||
	    ptr = (VALUE)obj->as.node.u3.node;
 | 
						    ptr = (VALUE)obj->as.node.u3.node;
 | 
				
			||||||
	    goto again;
 | 
						    goto again;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  case NODE_WHILE:	/* 1,2 */
 | 
						  case NODE_METHOD:	/* 1,2 */
 | 
				
			||||||
 | 
						  case NODE_WHILE:
 | 
				
			||||||
	  case NODE_UNTIL:
 | 
						  case NODE_UNTIL:
 | 
				
			||||||
	  case NODE_AND:
 | 
						  case NODE_AND:
 | 
				
			||||||
	  case NODE_OR:
 | 
						  case NODE_OR:
 | 
				
			||||||
| 
						 | 
					@ -831,10 +887,9 @@ gc_mark_children(VALUE ptr, int lev)
 | 
				
			||||||
	  case NODE_MODULE:
 | 
						  case NODE_MODULE:
 | 
				
			||||||
	  case NODE_ALIAS:
 | 
						  case NODE_ALIAS:
 | 
				
			||||||
	  case NODE_VALIAS:
 | 
						  case NODE_VALIAS:
 | 
				
			||||||
	  case NODE_LAMBDA:
 | 
					 | 
				
			||||||
	    gc_mark((VALUE)obj->as.node.u1.node, lev);
 | 
						    gc_mark((VALUE)obj->as.node.u1.node, lev);
 | 
				
			||||||
	    /* fall through */
 | 
						    /* fall through */
 | 
				
			||||||
	  case NODE_METHOD:	/* 2 */
 | 
						  case NODE_FBODY:	/* 2 */
 | 
				
			||||||
	  case NODE_NOT:
 | 
						  case NODE_NOT:
 | 
				
			||||||
	  case NODE_GASGN:
 | 
						  case NODE_GASGN:
 | 
				
			||||||
	  case NODE_LASGN:
 | 
						  case NODE_LASGN:
 | 
				
			||||||
| 
						 | 
					@ -932,7 +987,6 @@ gc_mark_children(VALUE ptr, int lev)
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
	    long i, len = RARRAY_LEN(obj);
 | 
						    long i, len = RARRAY_LEN(obj);
 | 
				
			||||||
	    VALUE *ptr = RARRAY_PTR(obj);
 | 
						    VALUE *ptr = RARRAY_PTR(obj);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	    for (i=0; i < len; i++) {
 | 
						    for (i=0; i < len; i++) {
 | 
				
			||||||
		gc_mark(*ptr++, lev);
 | 
							gc_mark(*ptr++, lev);
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
| 
						 | 
					@ -968,29 +1022,13 @@ gc_mark_children(VALUE ptr, int lev)
 | 
				
			||||||
	break;
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case T_MATCH:
 | 
					      case T_MATCH:
 | 
				
			||||||
        gc_mark(obj->as.match.regexp, lev);
 | 
						gc_mark(obj->as.match.regexp, lev);
 | 
				
			||||||
	if (obj->as.match.str) {
 | 
						if (obj->as.match.str) {
 | 
				
			||||||
	    ptr = obj->as.match.str;
 | 
						    ptr = obj->as.match.str;
 | 
				
			||||||
	    goto again;
 | 
						    goto again;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	break;
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case T_VARMAP:
 | 
					 | 
				
			||||||
	gc_mark(obj->as.varmap.val, lev);
 | 
					 | 
				
			||||||
	ptr = (VALUE)obj->as.varmap.next;
 | 
					 | 
				
			||||||
	goto again;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      case T_SCOPE:
 | 
					 | 
				
			||||||
	if (obj->as.scope.local_vars && (obj->as.scope.flags & SCOPE_MALLOC)) {
 | 
					 | 
				
			||||||
	    int n = obj->as.scope.local_tbl[0]+1;
 | 
					 | 
				
			||||||
	    VALUE *vars = &obj->as.scope.local_vars[-1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	    while (n--) {
 | 
					 | 
				
			||||||
		gc_mark(*vars++, lev);
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      case T_STRUCT:
 | 
					      case T_STRUCT:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	    long len = RSTRUCT_LEN(obj);
 | 
						    long len = RSTRUCT_LEN(obj);
 | 
				
			||||||
| 
						 | 
					@ -1002,6 +1040,15 @@ gc_mark_children(VALUE ptr, int lev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	break;
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case T_VALUES:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					            rb_gc_mark(RVALUES(obj)->v1);
 | 
				
			||||||
 | 
					            rb_gc_mark(RVALUES(obj)->v2);
 | 
				
			||||||
 | 
					            ptr = RVALUES(obj)->v3;
 | 
				
			||||||
 | 
					            goto again;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
	rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
 | 
						rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
 | 
				
			||||||
	       obj->as.basic.flags & T_MASK, obj,
 | 
						       obj->as.basic.flags & T_MASK, obj,
 | 
				
			||||||
| 
						 | 
					@ -1054,14 +1101,6 @@ gc_sweep(void)
 | 
				
			||||||
    int freed = 0;
 | 
					    int freed = 0;
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    unsigned long live = 0;
 | 
					    unsigned long live = 0;
 | 
				
			||||||
    unsigned long free_min = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < heaps_used; i++) {
 | 
					 | 
				
			||||||
        free_min += heaps[i].limit;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    free_min = free_min * 0.2;
 | 
					 | 
				
			||||||
    if (free_min < FREE_MIN)
 | 
					 | 
				
			||||||
        free_min = FREE_MIN;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mark_source_filename(ruby_sourcefile);
 | 
					    mark_source_filename(ruby_sourcefile);
 | 
				
			||||||
    if (source_filenames) {
 | 
					    if (source_filenames) {
 | 
				
			||||||
| 
						 | 
					@ -1104,12 +1143,12 @@ gc_sweep(void)
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	    p++;
 | 
						    p++;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (n == heaps[i].limit && freed > free_min) {
 | 
						if (n == heaps[i].limit && freed > FREE_MIN) {
 | 
				
			||||||
	    RVALUE *pp;
 | 
						    RVALUE *pp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    heaps[i].limit = 0;
 | 
						    heaps[i].limit = 0;
 | 
				
			||||||
	    for (pp = final_list; pp != final; pp = pp->as.free.next) {
 | 
						    for (pp = final_list; pp != final; pp = pp->as.free.next) {
 | 
				
			||||||
		pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */
 | 
							p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	    freelist = free;	/* cancel this page from freelist */
 | 
						    freelist = free;	/* cancel this page from freelist */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1122,7 +1161,7 @@ gc_sweep(void)
 | 
				
			||||||
	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
 | 
						if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    malloc_increase = 0;
 | 
					    malloc_increase = 0;
 | 
				
			||||||
    if (freed < free_min) {
 | 
					    if (freed < FREE_MIN) {
 | 
				
			||||||
	add_heap();
 | 
						add_heap();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    during_gc = 0;
 | 
					    during_gc = 0;
 | 
				
			||||||
| 
						 | 
					@ -1218,9 +1257,10 @@ obj_free(VALUE obj)
 | 
				
			||||||
	break;
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case T_FLOAT:
 | 
					      case T_FLOAT:
 | 
				
			||||||
      case T_VARMAP:
 | 
					 | 
				
			||||||
      case T_BLOCK:
 | 
					      case T_BLOCK:
 | 
				
			||||||
	break;
 | 
						break;
 | 
				
			||||||
 | 
					      case T_VALUES:
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case T_BIGNUM:
 | 
					      case T_BIGNUM:
 | 
				
			||||||
	if (RANY(obj)->as.bignum.digits) {
 | 
						if (RANY(obj)->as.bignum.digits) {
 | 
				
			||||||
| 
						 | 
					@ -1240,17 +1280,6 @@ obj_free(VALUE obj)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return;			/* no need to free iv_tbl */
 | 
						return;			/* no need to free iv_tbl */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case T_SCOPE:
 | 
					 | 
				
			||||||
	if (RANY(obj)->as.scope.local_vars &&
 | 
					 | 
				
			||||||
            RANY(obj)->as.scope.flags != SCOPE_ALLOCA) {
 | 
					 | 
				
			||||||
	    VALUE *vars = RANY(obj)->as.scope.local_vars-1;
 | 
					 | 
				
			||||||
	    if (vars[0] == 0)
 | 
					 | 
				
			||||||
		RUBY_CRITICAL(free(RANY(obj)->as.scope.local_tbl));
 | 
					 | 
				
			||||||
	    if (RANY(obj)->as.scope.flags & SCOPE_MALLOC)
 | 
					 | 
				
			||||||
		RUBY_CRITICAL(free(vars));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      case T_STRUCT:
 | 
					      case T_STRUCT:
 | 
				
			||||||
	if (RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK == 0 &&
 | 
						if (RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK == 0 &&
 | 
				
			||||||
	    RANY(obj)->as.rstruct.as.heap.ptr) {
 | 
						    RANY(obj)->as.rstruct.as.heap.ptr) {
 | 
				
			||||||
| 
						 | 
					@ -1264,12 +1293,6 @@ obj_free(VALUE obj)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					 | 
				
			||||||
rb_gc_mark_frame(struct FRAME *frame)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    gc_mark((VALUE)frame->node, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __GNUC__
 | 
					#ifdef __GNUC__
 | 
				
			||||||
#if defined(__human68k__) || defined(DJGPP)
 | 
					#if defined(__human68k__) || defined(DJGPP)
 | 
				
			||||||
#if defined(__human68k__)
 | 
					#if defined(__human68k__)
 | 
				
			||||||
| 
						 | 
					@ -1308,20 +1331,21 @@ int rb_setjmp (rb_jmp_buf);
 | 
				
			||||||
#endif /* __human68k__ or DJGPP */
 | 
					#endif /* __human68k__ or DJGPP */
 | 
				
			||||||
#endif /* __GNUC__ */
 | 
					#endif /* __GNUC__ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GC_NOTIFY 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
garbage_collect(void)
 | 
					garbage_collect(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct gc_list *list;
 | 
					    struct gc_list *list;
 | 
				
			||||||
    struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */
 | 
					 | 
				
			||||||
    jmp_buf save_regs_gc_mark;
 | 
					    jmp_buf save_regs_gc_mark;
 | 
				
			||||||
    SET_STACK_END;
 | 
					    yarv_thread_t *th = GET_THREAD();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!heaps) return Qfalse;
 | 
					    if (GC_NOTIFY) printf("start garbage_collect()\n");
 | 
				
			||||||
#ifdef HAVE_NATIVETHREAD
 | 
					
 | 
				
			||||||
    if (!is_ruby_native_thread()) {
 | 
					    if (!heaps) {
 | 
				
			||||||
	rb_bug("cross-thread violation on rb_gc()");
 | 
						return Qfalse;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					
 | 
				
			||||||
    if (dont_gc || during_gc) {
 | 
					    if (dont_gc || during_gc) {
 | 
				
			||||||
	if (!freelist) {
 | 
						if (!freelist) {
 | 
				
			||||||
	    add_heap();
 | 
						    add_heap();
 | 
				
			||||||
| 
						 | 
					@ -1330,23 +1354,13 @@ garbage_collect(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    during_gc++;
 | 
					    during_gc++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    YARV_SET_STACK_END;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    init_mark_stack();
 | 
					    init_mark_stack();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gc_mark((VALUE)ruby_current_node, 0);
 | 
					    rb_gc_mark(th->vm->self);
 | 
				
			||||||
 | 
					    rb_gc_mark(th->vm->mark_object_ary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* mark frame stack */
 | 
					 | 
				
			||||||
    for (frame = ruby_frame; frame; frame = frame->prev) {
 | 
					 | 
				
			||||||
	rb_gc_mark_frame(frame);
 | 
					 | 
				
			||||||
	if (frame->tmp) {
 | 
					 | 
				
			||||||
	    struct FRAME *tmp = frame->tmp;
 | 
					 | 
				
			||||||
	    while (tmp) {
 | 
					 | 
				
			||||||
		rb_gc_mark_frame(tmp);
 | 
					 | 
				
			||||||
		tmp = tmp->prev;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    gc_mark((VALUE)ruby_scope, 0);
 | 
					 | 
				
			||||||
    gc_mark((VALUE)ruby_dyna_vars, 0);
 | 
					 | 
				
			||||||
    if (finalizer_table) {
 | 
					    if (finalizer_table) {
 | 
				
			||||||
	mark_tbl(finalizer_table, 0);
 | 
						mark_tbl(finalizer_table, 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -1355,24 +1369,45 @@ garbage_collect(void)
 | 
				
			||||||
    /* This assumes that all registers are saved into the jmp_buf (and stack) */
 | 
					    /* This assumes that all registers are saved into the jmp_buf (and stack) */
 | 
				
			||||||
    setjmp(save_regs_gc_mark);
 | 
					    setjmp(save_regs_gc_mark);
 | 
				
			||||||
    mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
 | 
					    mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if STACK_GROW_DIRECTION < 0
 | 
					#if STACK_GROW_DIRECTION < 0
 | 
				
			||||||
    rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
 | 
					    rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
 | 
				
			||||||
#elif STACK_GROW_DIRECTION > 0
 | 
					#elif STACK_GROW_DIRECTION > 0
 | 
				
			||||||
    rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
 | 
					    rb_gc_mark_locations(th->machin_stack_start, th->machine_stack_end + 1);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    if ((VALUE*)STACK_END < rb_gc_stack_start)
 | 
					    if (th->machine_stack_end < th->machin_stack_start)
 | 
				
			||||||
	rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
 | 
					      rb_gc_mark_locations(th->machine_stack_end, th->machin_stack_start);
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
	rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
 | 
					      rb_gc_mark_locations(th->machin_stack_start, th->machine_stack_end + 1);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef __ia64
 | 
					#ifdef __ia64__
 | 
				
			||||||
    /* mark backing store (flushed register stack) */
 | 
					    /* mark backing store (flushed register window on the stack) */
 | 
				
			||||||
    /* the basic idea from guile GC code                         */
 | 
					    /* the basic idea from guile GC code                         */
 | 
				
			||||||
    rb_gc_mark_locations(rb_gc_register_stack_start, (VALUE*)rb_ia64_bsp());
 | 
					    {
 | 
				
			||||||
 | 
						ucontext_t ctx;
 | 
				
			||||||
 | 
						VALUE *top, *bot;
 | 
				
			||||||
 | 
					#if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
 | 
				
			||||||
 | 
						_Unwind_Context *unwctx = _UNW_createContextForSelf();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						getcontext(&ctx);
 | 
				
			||||||
 | 
						mark_locations_array((VALUE*)&ctx.uc_mcontext,
 | 
				
			||||||
 | 
								     ((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
 | 
				
			||||||
 | 
					#if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
 | 
				
			||||||
 | 
						_UNW_currentContext(unwctx);
 | 
				
			||||||
 | 
						bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
 | 
				
			||||||
 | 
						top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
 | 
				
			||||||
 | 
						_UNW_destroyContext(unwctx);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						bot = (VALUE*)__libc_ia64_register_backing_store_base;
 | 
				
			||||||
 | 
						top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						rb_gc_mark_locations(bot, top);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#if defined(__human68k__) || defined(__mc68000__)
 | 
					#if defined(__human68k__) || defined(__mc68000__)
 | 
				
			||||||
    rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
 | 
					    rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
 | 
				
			||||||
			 (VALUE*)((char*)rb_gc_stack_start + 2));
 | 
								 (VALUE*)((char*)STACK_START + 2));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    rb_gc_mark_threads();
 | 
					    rb_gc_mark_threads();
 | 
				
			||||||
    rb_gc_mark_symbols();
 | 
					    rb_gc_mark_symbols();
 | 
				
			||||||
| 
						 | 
					@ -1393,23 +1428,38 @@ garbage_collect(void)
 | 
				
			||||||
    rb_gc_mark_parser();
 | 
					    rb_gc_mark_parser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* gc_mark objects whose marking are not completed*/
 | 
					    /* gc_mark objects whose marking are not completed*/
 | 
				
			||||||
    do {
 | 
					    while (!MARK_STACK_EMPTY){
 | 
				
			||||||
	while (!MARK_STACK_EMPTY) {
 | 
						if (mark_stack_overflow){
 | 
				
			||||||
	    if (mark_stack_overflow){
 | 
						    gc_mark_all();
 | 
				
			||||||
		gc_mark_all();
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    else {
 | 
					 | 
				
			||||||
		gc_mark_rest();
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rb_gc_abort_threads();
 | 
						else {
 | 
				
			||||||
    } while (!MARK_STACK_EMPTY);
 | 
						    gc_mark_rest();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gc_sweep();
 | 
					    gc_sweep();
 | 
				
			||||||
 | 
					    if (GC_NOTIFY) printf("end garbage_collect()\n");
 | 
				
			||||||
    return Qtrue;
 | 
					    return Qtrue;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					yarv_machine_stack_mark(yarv_thread_t *th)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if STACK_GROW_DIRECTION < 0
 | 
				
			||||||
 | 
					    rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
 | 
				
			||||||
 | 
					#elif STACK_GROW_DIRECTION > 0
 | 
				
			||||||
 | 
					    rb_gc_mark_locations(th->machin_stack_start, th->machine_stack_end);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    if (th->machin_stack_start < th->machine_stack_end) {
 | 
				
			||||||
 | 
						rb_gc_mark_locations(th->machin_stack_start, th->machine_stack_end);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
						rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
rb_gc(void)
 | 
					rb_gc(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1604,8 +1654,6 @@ os_live_obj(void)
 | 
				
			||||||
	    if (p->as.basic.flags) {
 | 
						    if (p->as.basic.flags) {
 | 
				
			||||||
		switch (TYPE(p)) {
 | 
							switch (TYPE(p)) {
 | 
				
			||||||
		  case T_ICLASS:
 | 
							  case T_ICLASS:
 | 
				
			||||||
		  case T_VARMAP:
 | 
					 | 
				
			||||||
		  case T_SCOPE:
 | 
					 | 
				
			||||||
		  case T_NODE:
 | 
							  case T_NODE:
 | 
				
			||||||
		    continue;
 | 
							    continue;
 | 
				
			||||||
		  case T_CLASS:
 | 
							  case T_CLASS:
 | 
				
			||||||
| 
						 | 
					@ -1636,8 +1684,6 @@ os_obj_of(VALUE of)
 | 
				
			||||||
	    if (p->as.basic.flags) {
 | 
						    if (p->as.basic.flags) {
 | 
				
			||||||
		switch (TYPE(p)) {
 | 
							switch (TYPE(p)) {
 | 
				
			||||||
		  case T_ICLASS:
 | 
							  case T_ICLASS:
 | 
				
			||||||
		  case T_VARMAP:
 | 
					 | 
				
			||||||
		  case T_SCOPE:
 | 
					 | 
				
			||||||
		  case T_NODE:
 | 
							  case T_NODE:
 | 
				
			||||||
		    continue;
 | 
							    continue;
 | 
				
			||||||
		  case T_CLASS:
 | 
							  case T_CLASS:
 | 
				
			||||||
| 
						 | 
					@ -1796,7 +1842,7 @@ define_final(int argc, VALUE *argv, VALUE os)
 | 
				
			||||||
    need_call_final = 1;
 | 
					    need_call_final = 1;
 | 
				
			||||||
    FL_SET(obj, FL_FINALIZE);
 | 
					    FL_SET(obj, FL_FINALIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    block = rb_ary_new3(2, INT2FIX(ruby_safe_level), block);
 | 
					    block = rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!finalizer_table) {
 | 
					    if (!finalizer_table) {
 | 
				
			||||||
	finalizer_table = st_init_numtable();
 | 
						finalizer_table = st_init_numtable();
 | 
				
			||||||
| 
						 | 
					@ -1840,7 +1886,7 @@ run_final(VALUE obj)
 | 
				
			||||||
    objid = rb_obj_id(obj);	/* make obj into id */
 | 
					    objid = rb_obj_id(obj);	/* make obj into id */
 | 
				
			||||||
    rb_thread_critical = Qtrue;
 | 
					    rb_thread_critical = Qtrue;
 | 
				
			||||||
    args[1] = 0;
 | 
					    args[1] = 0;
 | 
				
			||||||
    args[2] = (VALUE)ruby_safe_level;
 | 
					    args[2] = (VALUE)rb_safe_level();
 | 
				
			||||||
    for (i=0; i<RARRAY_LEN(finalizers); i++) {
 | 
					    for (i=0; i<RARRAY_LEN(finalizers); i++) {
 | 
				
			||||||
	args[0] = RARRAY_PTR(finalizers)[i];
 | 
						args[0] = RARRAY_PTR(finalizers)[i];
 | 
				
			||||||
	if (!args[1]) args[1] = rb_ary_new3(1, objid);
 | 
						if (!args[1]) args[1] = rb_ary_new3(1, objid);
 | 
				
			||||||
| 
						 | 
					@ -1960,8 +2006,8 @@ id2ref(VALUE obj, VALUE objid)
 | 
				
			||||||
    if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
 | 
					    if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
 | 
				
			||||||
        ID symid = ptr / sizeof(RVALUE);
 | 
					        ID symid = ptr / sizeof(RVALUE);
 | 
				
			||||||
        if (rb_id2name(symid) == 0)
 | 
					        if (rb_id2name(symid) == 0)
 | 
				
			||||||
            rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
 | 
						  rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
 | 
				
			||||||
        return ID2SYM(symid);
 | 
						return ID2SYM(symid);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!is_pointer_to_heap((void *)ptr)|| BUILTIN_TYPE(ptr) >= T_BLOCK) {
 | 
					    if (!is_pointer_to_heap((void *)ptr)|| BUILTIN_TYPE(ptr) >= T_BLOCK) {
 | 
				
			||||||
| 
						 | 
					@ -2011,7 +2057,7 @@ rb_obj_id(VALUE obj)
 | 
				
			||||||
     *  nil     00000000000000000000000000000100
 | 
					     *  nil     00000000000000000000000000000100
 | 
				
			||||||
     *  undef   00000000000000000000000000000110
 | 
					     *  undef   00000000000000000000000000000110
 | 
				
			||||||
     *  symbol  ssssssssssssssssssssssss00001110
 | 
					     *  symbol  ssssssssssssssssssssssss00001110
 | 
				
			||||||
     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE))
 | 
					     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE)
 | 
				
			||||||
     *  fixnum  fffffffffffffffffffffffffffffff1
 | 
					     *  fixnum  fffffffffffffffffffffffffffffff1
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     *                    object_id space
 | 
					     *                    object_id space
 | 
				
			||||||
| 
						 | 
					@ -2020,7 +2066,7 @@ rb_obj_id(VALUE obj)
 | 
				
			||||||
     *  true    00000000000000000000000000000010
 | 
					     *  true    00000000000000000000000000000010
 | 
				
			||||||
     *  nil     00000000000000000000000000000100
 | 
					     *  nil     00000000000000000000000000000100
 | 
				
			||||||
     *  undef   00000000000000000000000000000110
 | 
					     *  undef   00000000000000000000000000000110
 | 
				
			||||||
     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
 | 
					     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = 
 | 
				
			||||||
     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
 | 
					     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
 | 
				
			||||||
     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
 | 
					     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -2031,6 +2077,9 @@ rb_obj_id(VALUE obj)
 | 
				
			||||||
     *  24 if 32-bit, double is 8-byte aligned
 | 
					     *  24 if 32-bit, double is 8-byte aligned
 | 
				
			||||||
     *  40 if 64-bit
 | 
					     *  40 if 64-bit
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					    if (TYPE(obj) == T_SYMBOL) {
 | 
				
			||||||
 | 
					        return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (SPECIAL_CONST_P(obj)) {
 | 
					    if (SPECIAL_CONST_P(obj)) {
 | 
				
			||||||
        return LONG2NUM((long)obj);
 | 
					        return LONG2NUM((long)obj);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -2079,7 +2128,7 @@ Init_GC(void)
 | 
				
			||||||
    rb_global_variable(&nomem_error);
 | 
					    rb_global_variable(&nomem_error);
 | 
				
			||||||
    nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
 | 
					    nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rb_define_method(rb_cBasicObject, "__id__", rb_obj_id, 0);
 | 
					 | 
				
			||||||
    rb_define_method(rb_cBasicObject, "object_id", rb_obj_id, 0);
 | 
					 | 
				
			||||||
    rb_define_method(rb_mKernel, "hash", rb_obj_id, 0);
 | 
					    rb_define_method(rb_mKernel, "hash", rb_obj_id, 0);
 | 
				
			||||||
 | 
					    rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
 | 
				
			||||||
 | 
					    rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue