mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
See this ticet about RGENGC. * gc.c: Add several flags: * RGENGC_DEBUG: if >0, then prints debug information. * RGENGC_CHECK_MODE: if >0, add assertions. * RGENGC_PROFILE: if >0, add profiling features. check GC.stat and GC::Profiler. * include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0). * array.c: add write barriers for T_ARRAY and generate sunny objects. * include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if you want to access raw pointers. If you modify the contents which pointer pointed, then you need to care write barrier. * bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects. * complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX and generate sunny objects. * rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write barriers for T_RATIONAL and generate sunny objects. * internal.h: add write barriers for RBasic::klass. * numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects. * object.c (rb_class_allocate_instance), range.c: generate sunny T_OBJECT objects. * string.c: add write barriers for T_STRING and generate sunny objects. * variable.c: add write barriers for ivars. * vm_insnhelper.c (vm_setivar): ditto. * include/ruby/ruby.h, debug.c: use two flags FL_WB_PROTECTED and FL_OLDGEN. * node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED): move flag bits. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									7958c71ee5
								
							
						
					
					
						commit
						4f401816ff
					
				
					 18 changed files with 1005 additions and 155 deletions
				
			
		
							
								
								
									
										46
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,49 @@
 | 
			
		|||
Tue May 14 02:47:30 2013  Koichi Sasada  <ko1@atdot.net>
 | 
			
		||||
 | 
			
		||||
	* gc.c: support RGENGC. [ruby-trunk - Feature #8339]
 | 
			
		||||
	  See this ticet about RGENGC.
 | 
			
		||||
 | 
			
		||||
	* gc.c: Add several flags:
 | 
			
		||||
	  * RGENGC_DEBUG: if >0, then prints debug information.
 | 
			
		||||
	  * RGENGC_CHECK_MODE: if >0, add assertions.
 | 
			
		||||
	  * RGENGC_PROFILE: if >0, add profiling features.
 | 
			
		||||
	    check GC.stat and GC::Profiler.
 | 
			
		||||
 | 
			
		||||
	* include/ruby/ruby.h: disable RGENGC by default (USE_RGENGC == 0).
 | 
			
		||||
 | 
			
		||||
	* array.c: add write barriers for T_ARRAY and generate sunny objects.
 | 
			
		||||
 | 
			
		||||
	* include/ruby/ruby.h (RARRAY_PTR_USE): added. Use this macro if
 | 
			
		||||
	  you want to access raw pointers. If you modify the contents which
 | 
			
		||||
	  pointer pointed, then you need to care write barrier.
 | 
			
		||||
 | 
			
		||||
	* bignum.c, marshal.c, random.c: generate T_BIGNUM sunny objects.
 | 
			
		||||
 | 
			
		||||
	* complex.c, include/ruby/ruby.h: add write barriers for T_COMPLEX
 | 
			
		||||
	  and generate sunny objects.
 | 
			
		||||
 | 
			
		||||
	* rational.c (nurat_s_new_internal), include/ruby/ruby.h: add write
 | 
			
		||||
	  barriers for T_RATIONAL and generate sunny objects.
 | 
			
		||||
 | 
			
		||||
	* internal.h: add write barriers for RBasic::klass.
 | 
			
		||||
 | 
			
		||||
	* numeric.c (rb_float_new_in_heap): generate sunny T_FLOAT objects.
 | 
			
		||||
 | 
			
		||||
	* object.c (rb_class_allocate_instance), range.c:
 | 
			
		||||
	  generate sunny T_OBJECT objects.
 | 
			
		||||
 | 
			
		||||
	* string.c: add write barriers for T_STRING and generate sunny objects.
 | 
			
		||||
 | 
			
		||||
	* variable.c: add write barriers for ivars.
 | 
			
		||||
 | 
			
		||||
	* vm_insnhelper.c (vm_setivar): ditto.
 | 
			
		||||
 | 
			
		||||
	* include/ruby/ruby.h, debug.c: use two flags
 | 
			
		||||
	  FL_WB_PROTECTED and FL_OLDGEN.
 | 
			
		||||
 | 
			
		||||
	* node.h (NODE_FL_CREF_PUSHED_BY_EVAL, NODE_FL_CREF_OMOD_SHARED):
 | 
			
		||||
	  move flag bits.
 | 
			
		||||
 | 
			
		||||
Tue May 14 01:54:48 2013  Koichi Sasada  <ko1@atdot.net>
 | 
			
		||||
 | 
			
		||||
	* gc.c: remove rb_objspace_t::marked_num.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								array.c
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								array.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -128,10 +128,12 @@ memfill(register VALUE *mem, register long size, register VALUE val)
 | 
			
		|||
 | 
			
		||||
#define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
 | 
			
		||||
#define ARY_SET_SHARED(ary, value) do { \
 | 
			
		||||
    assert(!ARY_EMBED_P(ary)); \
 | 
			
		||||
    assert(ARY_SHARED_P(ary)); \
 | 
			
		||||
    assert(ARY_SHARED_ROOT_P(value)); \
 | 
			
		||||
    RARRAY(ary)->as.heap.aux.shared = (value); \
 | 
			
		||||
    const VALUE _ary_ = (ary); \
 | 
			
		||||
    const VALUE _value_ = (value); \
 | 
			
		||||
    assert(!ARY_EMBED_P(_ary_)); \
 | 
			
		||||
    assert(ARY_SHARED_P(_ary_)); \
 | 
			
		||||
    assert(ARY_SHARED_ROOT_P(_value_)); \
 | 
			
		||||
    OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared, _value_); \
 | 
			
		||||
} while (0)
 | 
			
		||||
#define RARRAY_SHARED_ROOT_FLAG FL_USER5
 | 
			
		||||
#define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG))
 | 
			
		||||
| 
						 | 
				
			
			@ -370,7 +372,7 @@ rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
 | 
			
		|||
static VALUE
 | 
			
		||||
ary_alloc(VALUE klass)
 | 
			
		||||
{
 | 
			
		||||
    NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY);
 | 
			
		||||
    NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
 | 
			
		||||
    FL_SET_EMBED((VALUE)ary);
 | 
			
		||||
    ARY_SET_EMBED_LEN((VALUE)ary, 0);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -409,6 +411,14 @@ ary_new(VALUE klass, long capa)
 | 
			
		|||
        ARY_SET_PTR(ary, ALLOC_N(VALUE, capa));
 | 
			
		||||
        ARY_SET_CAPA(ary, capa);
 | 
			
		||||
        ARY_SET_HEAP_LEN(ary, 0);
 | 
			
		||||
 | 
			
		||||
	/* NOTE: `ary' can be old because the following suquence is possible.
 | 
			
		||||
	 *   (1) ary = ary_alloc();
 | 
			
		||||
	 *   (2) GC (for (3))          -> promote ary
 | 
			
		||||
	 *   (3) ALLOC_N(VALUE, capa)
 | 
			
		||||
	 * So that force ary as young object.
 | 
			
		||||
	 */
 | 
			
		||||
	RBASIC(ary)->flags &= ~FL_OLDGEN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ary;
 | 
			
		||||
| 
						 | 
				
			
			@ -455,7 +465,9 @@ rb_ary_new4(long n, const VALUE *elts)
 | 
			
		|||
 | 
			
		||||
    ary = rb_ary_new2(n);
 | 
			
		||||
    if (n > 0 && elts) {
 | 
			
		||||
	MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
 | 
			
		||||
	RARRAY_PTR_USE(ary, ptr, {
 | 
			
		||||
	    MEMCPY(ptr, elts, VALUE, n); /* new array is not old gen */
 | 
			
		||||
	});
 | 
			
		||||
	ARY_SET_LEN(ary, n);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -512,7 +524,7 @@ ary_make_shared(VALUE ary)
 | 
			
		|||
	return ary;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY);
 | 
			
		||||
	NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
 | 
			
		||||
        FL_UNSET_EMBED(shared);
 | 
			
		||||
 | 
			
		||||
        ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary));
 | 
			
		||||
| 
						 | 
				
			
			@ -649,8 +661,8 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
 | 
			
		|||
 | 
			
		||||
    rb_ary_modify(ary);
 | 
			
		||||
    if (argc == 0) {
 | 
			
		||||
	if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
 | 
			
		||||
	    xfree(RARRAY_PTR(ary));
 | 
			
		||||
	if (ARY_OWNS_HEAP_P(ary) && RARRAY_RAWPTR(ary) != 0) {
 | 
			
		||||
	    xfree(RARRAY_RAWPTR(ary));
 | 
			
		||||
	}
 | 
			
		||||
        rb_ary_unshare_safe(ary);
 | 
			
		||||
        FL_SET_EMBED(ary);
 | 
			
		||||
| 
						 | 
				
			
			@ -690,7 +702,10 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
 | 
			
		|||
	}
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	memfill(RARRAY_PTR(ary), len, val);
 | 
			
		||||
	RARRAY_PTR_USE(ary, ptr, {
 | 
			
		||||
	    memfill(ptr, len, val);
 | 
			
		||||
	});
 | 
			
		||||
	OBJ_WRITTEN(ary, Qundef, val);
 | 
			
		||||
	ARY_SET_LEN(ary, len);
 | 
			
		||||
    }
 | 
			
		||||
    return ary;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								bignum.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								bignum.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -166,7 +166,7 @@ rb_big_resize(VALUE big, long len)
 | 
			
		|||
static VALUE
 | 
			
		||||
bignew_1(VALUE klass, long len, int sign)
 | 
			
		||||
{
 | 
			
		||||
    NEWOBJ_OF(big, struct RBignum, klass, T_BIGNUM);
 | 
			
		||||
    NEWOBJ_OF(big, struct RBignum, klass, T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0));
 | 
			
		||||
    RBIGNUM_SET_SIGN(big, sign?1:0);
 | 
			
		||||
    if (len <= RBIGNUM_EMBED_LEN_MAX) {
 | 
			
		||||
	RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -313,7 +313,7 @@ k_complex_p(VALUE x)
 | 
			
		|||
inline static VALUE
 | 
			
		||||
nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
 | 
			
		||||
{
 | 
			
		||||
    NEWOBJ_OF(obj, struct RComplex, klass, T_COMPLEX);
 | 
			
		||||
    NEWOBJ_OF(obj, struct RComplex, klass, T_COMPLEX | (RGENGC_WB_PROTECTED_COMPLEX ? FL_WB_PROTECTED : 0));
 | 
			
		||||
 | 
			
		||||
    RCOMPLEX_SET_REAL(obj, real);
 | 
			
		||||
    RCOMPLEX_SET_IMAG(obj, imag);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								debug.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								debug.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -32,8 +32,8 @@ const union {
 | 
			
		|||
        RUBY_ENC_CODERANGE_7BIT    = ENC_CODERANGE_7BIT,
 | 
			
		||||
        RUBY_ENC_CODERANGE_VALID   = ENC_CODERANGE_VALID,
 | 
			
		||||
        RUBY_ENC_CODERANGE_BROKEN  = ENC_CODERANGE_BROKEN,
 | 
			
		||||
        RUBY_FL_RESERVED1   = FL_RESERVED1,
 | 
			
		||||
        RUBY_FL_RESERVED2   = FL_RESERVED2,
 | 
			
		||||
        RUBY_FL_WB_PROTECTED     = FL_WB_PROTECTED,
 | 
			
		||||
        RUBY_FL_OLDGEN      = FL_OLDGEN,
 | 
			
		||||
        RUBY_FL_FINALIZE    = FL_FINALIZE,
 | 
			
		||||
        RUBY_FL_TAINT       = FL_TAINT,
 | 
			
		||||
        RUBY_FL_UNTRUSTED   = FL_UNTRUSTED,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -681,6 +681,32 @@ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
 | 
			
		|||
    if (FL_TEST((obj), FL_EXIVAR)) rb_copy_generic_ivar((VALUE)(dup),(VALUE)(obj));\
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#ifndef USE_RGENGC
 | 
			
		||||
#define USE_RGENGC 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef RGENGC_WB_PROTECTED_ARRAY
 | 
			
		||||
#define RGENGC_WB_PROTECTED_ARRAY 0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RGENGC_WB_PROTECTED_STRING
 | 
			
		||||
#define RGENGC_WB_PROTECTED_STRING 0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RGENGC_WB_PROTECTED_OBJECT
 | 
			
		||||
#define RGENGC_WB_PROTECTED_OBJECT 0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RGENGC_WB_PROTECTED_FLOAT
 | 
			
		||||
#define RGENGC_WB_PROTECTED_FLOAT 0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RGENGC_WB_PROTECTED_COMPLEX
 | 
			
		||||
#define RGENGC_WB_PROTECTED_COMPLEX 0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RGENGC_WB_PROTECTED_RATIONAL
 | 
			
		||||
#define RGENGC_WB_PROTECTED_RATIONAL 0
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RGENGC_WB_PROTECTED_BIGNUM
 | 
			
		||||
#define RGENGC_WB_PROTECTED_BIGNUM 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct RBasic {
 | 
			
		||||
    VALUE flags;
 | 
			
		||||
    const VALUE klass;
 | 
			
		||||
| 
						 | 
				
			
			@ -891,14 +917,32 @@ struct RArray {
 | 
			
		|||
     (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
 | 
			
		||||
	 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)) : \
 | 
			
		||||
     RARRAY(a)->as.heap.len)
 | 
			
		||||
#define RARRAY_PTR(a) \
 | 
			
		||||
    ((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? \
 | 
			
		||||
     RARRAY(a)->as.ary : \
 | 
			
		||||
     RARRAY(a)->as.heap.ptr)
 | 
			
		||||
 | 
			
		||||
#define RARRAY_LENINT(ary) rb_long2int(RARRAY_LEN(ary))
 | 
			
		||||
 | 
			
		||||
#define RARRAY_AREF(a, i)    (RARRAY_PTR(a)[i])
 | 
			
		||||
#define RARRAY_ASET(a, i, v) do {RARRAY_PTR(a)[i] = (v);} while (0)
 | 
			
		||||
/* DO NOT USE THIS MACRO DIRECTLY */
 | 
			
		||||
#define RARRAY_RAWPTR(a) \
 | 
			
		||||
  ((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? \
 | 
			
		||||
   RARRAY(a)->as.ary : \
 | 
			
		||||
   RARRAY(a)->as.heap.ptr)
 | 
			
		||||
 | 
			
		||||
#define RARRAY_PTR_USE_START(a) RARRAY_RAWPTR(a)
 | 
			
		||||
#define RARRAY_PTR_USE_END(a) /* */
 | 
			
		||||
 | 
			
		||||
#define RARRAY_PTR_USE(ary, ptr_name, expr) do { \
 | 
			
		||||
    const VALUE _ary = (ary); \
 | 
			
		||||
    VALUE *ptr_name = RARRAY_PTR_USE_START(_ary); \
 | 
			
		||||
    expr; \
 | 
			
		||||
    RARRAY_PTR_USE_END(_ary); \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#define RARRAY_AREF(a, i)    (RARRAY_RAWPTR(a)[i])
 | 
			
		||||
#define RARRAY_ASET(a, i, v) do { \
 | 
			
		||||
    const VALUE _ary_ = (a); \
 | 
			
		||||
    OBJ_WRITE(_ary_, &RARRAY_RAWPTR(_ary_)[i], (v)); \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#define RARRAY_PTR(a) RARRAY_RAWPTR(RGENGC_WB_PROTECTED_ARRAY ? OBJ_WB_GIVEUP((VALUE)a) : ((VALUE)a))
 | 
			
		||||
 | 
			
		||||
struct RRegexp {
 | 
			
		||||
    struct RBasic basic;
 | 
			
		||||
| 
						 | 
				
			
			@ -935,8 +979,8 @@ struct RRational {
 | 
			
		|||
    const VALUE den;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define RRATIONAL_SET_NUM(rat, n) (*((VALUE *)(&((struct RRational *)(rat))->num)) = (n))
 | 
			
		||||
#define RRATIONAL_SET_DEN(rat, d) (*((VALUE *)(&((struct RRational *)(rat))->den)) = (d))
 | 
			
		||||
#define RRATIONAL_SET_NUM(rat, n) OBJ_WRITE((rat), ((VALUE *)(&((struct RRational *)(rat))->num)),(n))
 | 
			
		||||
#define RRATIONAL_SET_DEN(rat, d) OBJ_WRITE((rat), ((VALUE *)(&((struct RRational *)(rat))->den)),(d))
 | 
			
		||||
 | 
			
		||||
struct RComplex {
 | 
			
		||||
    struct RBasic basic;
 | 
			
		||||
| 
						 | 
				
			
			@ -944,8 +988,8 @@ struct RComplex {
 | 
			
		|||
    const VALUE imag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define RCOMPLEX_SET_REAL(cmp, r) (*((VALUE *)(&((struct RComplex *)(cmp))->real)) = (r))
 | 
			
		||||
#define RCOMPLEX_SET_IMAG(cmp, i) (*((VALUE *)(&((struct RComplex *)(cmp))->imag)) = (i))
 | 
			
		||||
#define RCOMPLEX_SET_REAL(cmp, r) OBJ_WRITE((cmp), ((VALUE *)(&((struct RComplex *)(cmp))->real)),(r))
 | 
			
		||||
#define RCOMPLEX_SET_IMAG(cmp, i) OBJ_WRITE((cmp), ((VALUE *)(&((struct RComplex *)(cmp))->imag)),(i))
 | 
			
		||||
 | 
			
		||||
struct RData {
 | 
			
		||||
    struct RBasic basic;
 | 
			
		||||
| 
						 | 
				
			
			@ -1108,8 +1152,8 @@ struct RBignum {
 | 
			
		|||
#define RCOMPLEX(obj) (R_CAST(RComplex)(obj))
 | 
			
		||||
 | 
			
		||||
#define FL_SINGLETON FL_USER0
 | 
			
		||||
#define FL_RESERVED1 (((VALUE)1)<<5)
 | 
			
		||||
#define FL_RESERVED2 (((VALUE)1)<<6) /* will be used in the future GC */
 | 
			
		||||
#define FL_WB_PROTECTED (((VALUE)1)<<5)
 | 
			
		||||
#define FL_OLDGEN    (((VALUE)1)<<6)
 | 
			
		||||
#define FL_FINALIZE  (((VALUE)1)<<7)
 | 
			
		||||
#define FL_TAINT     (((VALUE)1)<<8)
 | 
			
		||||
#define FL_UNTRUSTED (((VALUE)1)<<9)
 | 
			
		||||
| 
						 | 
				
			
			@ -1142,7 +1186,8 @@ struct RBignum {
 | 
			
		|||
#define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))
 | 
			
		||||
 | 
			
		||||
#define FL_ABLE(x) (!SPECIAL_CONST_P(x) && BUILTIN_TYPE(x) != T_NODE)
 | 
			
		||||
#define FL_TEST(x,f) (FL_ABLE(x)?(RBASIC(x)->flags&(f)):0)
 | 
			
		||||
#define FL_TEST_RAW(x,f) (RBASIC(x)->flags&(f))
 | 
			
		||||
#define FL_TEST(x,f) (FL_ABLE(x)?FL_TEST_RAW((x),(f)):0)
 | 
			
		||||
#define FL_ANY(x,f) FL_TEST((x),(f))
 | 
			
		||||
#define FL_ALL(x,f) (FL_TEST((x),(f)) == (f))
 | 
			
		||||
#define FL_SET(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags |= (f);} while (0)
 | 
			
		||||
| 
						 | 
				
			
			@ -1162,6 +1207,77 @@ struct RBignum {
 | 
			
		|||
#define OBJ_FROZEN(x) (!!(FL_ABLE(x)?(RBASIC(x)->flags&(FL_FREEZE)):(FIXNUM_P(x)||FLONUM_P(x))))
 | 
			
		||||
#define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE)
 | 
			
		||||
 | 
			
		||||
#if USE_RGENGC
 | 
			
		||||
#define OBJ_PROMOTED(x)             (SPECIAL_CONST_P(x) ? 0 : FL_TEST_RAW((x), FL_OLDGEN))
 | 
			
		||||
#define OBJ_WB_PROTECTED(x)         (SPECIAL_CONST_P(x) ? 1 : FL_TEST_RAW((x), FL_WB_PROTECTED))
 | 
			
		||||
#define OBJ_WB_GIVEUP(x)            rb_obj_wb_giveup(x, __FILE__, __LINE__)
 | 
			
		||||
 | 
			
		||||
void rb_gc_writebarrier(VALUE a, VALUE b);
 | 
			
		||||
void rb_gc_giveup_promoted_writebarrier(VALUE obj);
 | 
			
		||||
 | 
			
		||||
#else /* USE_RGENGC */
 | 
			
		||||
#define OBJ_PROMOTED(x)             0
 | 
			
		||||
#define OBJ_WB_PROTECTED(x)         0
 | 
			
		||||
#define OBJ_WB_GIVEUP(x)            rb_obj_wb_giveup(x, __FILE__, __LINE__)
 | 
			
		||||
#define OBJ_SHADE(x)                OBJ_WB_GIVEUP(x) /* RGENGC terminology */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define OBJ_WRITE(a, slot, b)       rb_obj_write((VALUE)(a), (slot), (VALUE)(b), __FILE__, __LINE__)
 | 
			
		||||
#define OBJ_WRITTEN(a, oldv, b)     rb_obj_written((VALUE)(a), (VALUE)(oldv), (VALUE)(b), __FILE__, __LINE__)
 | 
			
		||||
 | 
			
		||||
static inline VALUE
 | 
			
		||||
rb_obj_wb_giveup(VALUE x, const char *filename, int line)
 | 
			
		||||
{
 | 
			
		||||
#ifdef RGENGC_LOGGING_WB_GIVEUP
 | 
			
		||||
    RGENGC_LOGGING_WB_GIVEUP(x, filename, line);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if USE_RGENGC
 | 
			
		||||
    /* `x' should be an RVALUE object */
 | 
			
		||||
    if (FL_TEST_RAW((x), FL_WB_PROTECTED)) {
 | 
			
		||||
	RBASIC(x)->flags &= ~FL_WB_PROTECTED;
 | 
			
		||||
 | 
			
		||||
	if (FL_TEST_RAW((x), FL_OLDGEN)) {
 | 
			
		||||
	    rb_gc_giveup_promoted_writebarrier(x);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline VALUE
 | 
			
		||||
rb_obj_written(VALUE a, VALUE oldv, VALUE b, const char *filename, int line)
 | 
			
		||||
{
 | 
			
		||||
#ifdef RGENGC_LOGGING_OBJ_WRITTEN
 | 
			
		||||
    RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if USE_RGENGC
 | 
			
		||||
    /* `a' should be an RVALUE object */
 | 
			
		||||
    if (FL_TEST_RAW((a), FL_OLDGEN) &&
 | 
			
		||||
	!SPECIAL_CONST_P(b) && !FL_TEST_RAW((b), FL_OLDGEN)) {
 | 
			
		||||
	rb_gc_writebarrier(a, b);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline VALUE
 | 
			
		||||
rb_obj_write(VALUE a, VALUE *slot, VALUE b, const char *filename, int line)
 | 
			
		||||
{
 | 
			
		||||
#ifdef RGENGC_LOGGING_WRIET
 | 
			
		||||
    RGENGC_LOGGING_WRIET(a, slot, b, filename, line);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    *slot = b;
 | 
			
		||||
 | 
			
		||||
#if USE_RGENGC
 | 
			
		||||
    rb_obj_written(a, Qundef /* ignore `oldv' now */, b, filename, line);
 | 
			
		||||
#endif
 | 
			
		||||
    return a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if SIZEOF_INT < SIZEOF_LONG
 | 
			
		||||
# define INT2NUM(v) INT2FIX((int)(v))
 | 
			
		||||
# define UINT2NUM(v) LONG2FIX((unsigned int)(v))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -81,7 +81,7 @@ RCLASS_SUPER(VALUE c)
 | 
			
		|||
 | 
			
		||||
static inline VALUE
 | 
			
		||||
RCLASS_SET_SUPER(VALUE a, VALUE b) {
 | 
			
		||||
  RCLASS_EXT(a)->super = b;
 | 
			
		||||
  OBJ_WRITE(a, &RCLASS_EXT(a)->super, b);
 | 
			
		||||
  return b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +239,10 @@ struct RBasicRaw {
 | 
			
		|||
 | 
			
		||||
#define RBASIC_CLEAR_CLASS(obj)        (((struct RBasicRaw *)((VALUE)(obj)))->klass = 0)
 | 
			
		||||
#define RBASIC_SET_CLASS_RAW(obj, cls) (((struct RBasicRaw *)((VALUE)(obj)))->klass = (cls))
 | 
			
		||||
#define RBASIC_SET_CLASS(obj, cls)     do {((struct RBasicRaw *)(obj))->klass = cls; } while (0)
 | 
			
		||||
#define RBASIC_SET_CLASS(obj, cls)     do { \
 | 
			
		||||
    VALUE _obj_ = (obj); \
 | 
			
		||||
    OBJ_WRITE(_obj_, &((struct RBasicRaw *)(_obj_))->klass, cls); \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
/* parse.y */
 | 
			
		||||
VALUE rb_parser_get_yydebug(VALUE);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1613,7 +1613,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
 | 
			
		|||
	    BDIGIT *digits;
 | 
			
		||||
	    VALUE data;
 | 
			
		||||
 | 
			
		||||
	    NEWOBJ_OF(big, struct RBignum, rb_cBignum, T_BIGNUM);
 | 
			
		||||
	    NEWOBJ_OF(big, struct RBignum, rb_cBignum, T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0));
 | 
			
		||||
	    RBIGNUM_SET_SIGN(big, (r_byte(arg) == '+'));
 | 
			
		||||
	    len = r_long(arg);
 | 
			
		||||
	    data = r_bytes0(len * 2, arg);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								node.h
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								node.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -265,10 +265,16 @@ typedef struct RNode {
 | 
			
		|||
 | 
			
		||||
#define RNODE(obj)  (R_CAST(RNode)(obj))
 | 
			
		||||
 | 
			
		||||
/* 0..4:T_TYPES, 5:reserved, 6:NODE_FL_CREF_OMOD_SHARED, 7:NODE_FL_NEWLINE */
 | 
			
		||||
#define NODE_FL_NEWLINE (((VALUE)1)<<7)
 | 
			
		||||
#define NODE_FL_CREF_PUSHED_BY_EVAL NODE_FL_NEWLINE
 | 
			
		||||
#define NODE_FL_CREF_OMOD_SHARED (((VALUE)1)<<6)
 | 
			
		||||
/* FL     : 0..4: T_TYPES, 5: KEEP_WB, 6: OLDGEN, 7: FINALIZE, 8: TAINT, 9: UNTRUSTERD, 10: EXIVAR, 11: FREEZE */
 | 
			
		||||
/* NODE_FL: 0..4: T_TYPES, 5: KEEP_WB, 6: OLDGEN, 7: NODE_FL_NEWLINE|NODE_FL_CREF_PUSHED_BY_EVAL,
 | 
			
		||||
 *          8..14: nd_type,
 | 
			
		||||
 *          15..: nd_line or
 | 
			
		||||
 *          15: NODE_FL_CREF_PUSHED_BY_EVAL
 | 
			
		||||
 *          16: NODE_FL_CREF_OMOD_SHARED
 | 
			
		||||
 */
 | 
			
		||||
#define NODE_FL_NEWLINE             (((VALUE)1)<<7)
 | 
			
		||||
#define NODE_FL_CREF_PUSHED_BY_EVAL (((VALUE)1)<<15)
 | 
			
		||||
#define NODE_FL_CREF_OMOD_SHARED    (((VALUE)1)<<16)
 | 
			
		||||
 | 
			
		||||
#define NODE_TYPESHIFT 8
 | 
			
		||||
#define NODE_TYPEMASK  (((VALUE)0x7f)<<NODE_TYPESHIFT)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -637,7 +637,7 @@ num_to_int(VALUE num)
 | 
			
		|||
VALUE
 | 
			
		||||
rb_float_new_in_heap(double d)
 | 
			
		||||
{
 | 
			
		||||
    NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT);
 | 
			
		||||
    NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT | (RGENGC_WB_PROTECTED_FLOAT ? FL_WB_PROTECTED : 0));
 | 
			
		||||
 | 
			
		||||
    flt->float_value = d;
 | 
			
		||||
    OBJ_FREEZE(flt);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								object.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								object.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1800,7 +1800,7 @@ rb_obj_alloc(VALUE klass)
 | 
			
		|||
static VALUE
 | 
			
		||||
rb_class_allocate_instance(VALUE klass)
 | 
			
		||||
{
 | 
			
		||||
    NEWOBJ_OF(obj, struct RObject, klass, T_OBJECT);
 | 
			
		||||
    NEWOBJ_OF(obj, struct RObject, klass, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 0));
 | 
			
		||||
    return (VALUE)obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								random.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								random.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -540,7 +540,7 @@ make_seed_value(const void *ptr)
 | 
			
		|||
{
 | 
			
		||||
    const long len = DEFAULT_SEED_LEN/SIZEOF_BDIGITS;
 | 
			
		||||
    BDIGIT *digits;
 | 
			
		||||
    NEWOBJ_OF(big, struct RBignum, rb_cBignum, T_BIGNUM);
 | 
			
		||||
    NEWOBJ_OF(big, struct RBignum, rb_cBignum, T_BIGNUM | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
 | 
			
		||||
 | 
			
		||||
    RBIGNUM_SET_SIGN(big, 1);
 | 
			
		||||
    rb_big_resize((VALUE)big, len + 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								range.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								range.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1211,7 +1211,7 @@ static VALUE
 | 
			
		|||
range_dumper(VALUE range)
 | 
			
		||||
{
 | 
			
		||||
    VALUE v;
 | 
			
		||||
    NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT);
 | 
			
		||||
    NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 1));
 | 
			
		||||
 | 
			
		||||
    v = (VALUE)m;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -368,7 +368,7 @@ f_lcm(VALUE x, VALUE y)
 | 
			
		|||
inline static VALUE
 | 
			
		||||
nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
 | 
			
		||||
{
 | 
			
		||||
    NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL);
 | 
			
		||||
    NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL | (RGENGC_WB_PROTECTED_RATIONAL ? FL_WB_PROTECTED : 0));
 | 
			
		||||
 | 
			
		||||
    RRATIONAL_SET_NUM(obj, num);
 | 
			
		||||
    RRATIONAL_SET_DEN(obj, den);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								string.c
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								string.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -68,7 +68,6 @@ VALUE rb_cSymbol;
 | 
			
		|||
    if (FL_TEST((s),STR_NOEMBED)) FL_UNSET((s),(ELTS_SHARED|STR_ASSOC));\
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define STR_SET_NOEMBED(str) do {\
 | 
			
		||||
    FL_SET((str), STR_NOEMBED);\
 | 
			
		||||
    STR_SET_EMBED_LEN((str), 0);\
 | 
			
		||||
| 
						 | 
				
			
			@ -119,6 +118,11 @@ VALUE rb_cSymbol;
 | 
			
		|||
    }\
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#define STR_SET_SHARED(str, shared_str) do { \
 | 
			
		||||
    OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \
 | 
			
		||||
    FL_SET((str), ELTS_SHARED); \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
 | 
			
		||||
#define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -375,7 +379,7 @@ rb_str_capacity(VALUE str)
 | 
			
		|||
static inline VALUE
 | 
			
		||||
str_alloc(VALUE klass)
 | 
			
		||||
{
 | 
			
		||||
    NEWOBJ_OF(str, struct RString, klass, T_STRING);
 | 
			
		||||
    NEWOBJ_OF(str, struct RString, klass, T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0));
 | 
			
		||||
 | 
			
		||||
    str->as.heap.ptr = 0;
 | 
			
		||||
    str->as.heap.len = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -649,8 +653,7 @@ str_replace_shared_without_enc(VALUE str2, VALUE str)
 | 
			
		|||
	FL_SET(str2, STR_NOEMBED);
 | 
			
		||||
	RSTRING(str2)->as.heap.len = RSTRING_LEN(str);
 | 
			
		||||
	RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str);
 | 
			
		||||
	RSTRING(str2)->as.heap.aux.shared = str;
 | 
			
		||||
	FL_SET(str2, ELTS_SHARED);
 | 
			
		||||
	STR_SET_SHARED(str2, str);
 | 
			
		||||
    }
 | 
			
		||||
    return str2;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -699,12 +702,10 @@ str_new4(VALUE klass, VALUE str)
 | 
			
		|||
    if (STR_SHARED_P(str)) {
 | 
			
		||||
	VALUE shared = RSTRING(str)->as.heap.aux.shared;
 | 
			
		||||
	assert(OBJ_FROZEN(shared));
 | 
			
		||||
	FL_SET(str2, ELTS_SHARED);
 | 
			
		||||
	RSTRING(str2)->as.heap.aux.shared = shared;
 | 
			
		||||
	STR_SET_SHARED(str2, shared); /* TODO: WB is not needed because str2 is *new* object */
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	FL_SET(str, ELTS_SHARED);
 | 
			
		||||
	RSTRING(str)->as.heap.aux.shared = str2;
 | 
			
		||||
	STR_SET_SHARED(str, str2);
 | 
			
		||||
    }
 | 
			
		||||
    rb_enc_cr_str_exact_copy(str2, str);
 | 
			
		||||
    OBJ_INFECT(str2, str);
 | 
			
		||||
| 
						 | 
				
			
			@ -720,6 +721,9 @@ rb_str_new_frozen(VALUE orig)
 | 
			
		|||
    klass = rb_obj_class(orig);
 | 
			
		||||
    if (STR_SHARED_P(orig) && (str = RSTRING(orig)->as.heap.aux.shared)) {
 | 
			
		||||
	long ofs;
 | 
			
		||||
	if (!OBJ_FROZEN(str)) {
 | 
			
		||||
	    rb_bug("xyzzy");
 | 
			
		||||
	}
 | 
			
		||||
	assert(OBJ_FROZEN(str));
 | 
			
		||||
	ofs = RSTRING_LEN(str) - RSTRING_LEN(orig);
 | 
			
		||||
	if ((ofs > 0) || (klass != RBASIC(str)->klass) ||
 | 
			
		||||
| 
						 | 
				
			
			@ -742,7 +746,8 @@ rb_str_new_frozen(VALUE orig)
 | 
			
		|||
	FL_UNSET(orig, STR_ASSOC);
 | 
			
		||||
	str = str_new4(klass, orig);
 | 
			
		||||
	FL_SET(str, STR_ASSOC);
 | 
			
		||||
	RSTRING(str)->as.heap.aux.shared = assoc;
 | 
			
		||||
	OBJ_WRITE(str, &RSTRING(str)->as.heap.aux.shared, assoc);
 | 
			
		||||
	/* TODO: WB is not needed because str is new object */
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	str = str_new4(klass, orig);
 | 
			
		||||
| 
						 | 
				
			
			@ -878,8 +883,9 @@ rb_str_shared_replace(VALUE str, VALUE str2)
 | 
			
		|||
    RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
 | 
			
		||||
    RSTRING(str)->as.heap.len = RSTRING_LEN(str2);
 | 
			
		||||
    if (STR_NOCAPA_P(str2)) {
 | 
			
		||||
	VALUE shared = RSTRING(str2)->as.heap.aux.shared;
 | 
			
		||||
	FL_SET(str, RBASIC(str2)->flags & STR_NOCAPA);
 | 
			
		||||
	RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared;
 | 
			
		||||
	OBJ_WRITE(str, &RSTRING(str)->as.heap.aux.shared, shared);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa;
 | 
			
		||||
| 
						 | 
				
			
			@ -925,7 +931,7 @@ str_replace(VALUE str, VALUE str2)
 | 
			
		|||
	RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
 | 
			
		||||
	FL_SET(str, ELTS_SHARED);
 | 
			
		||||
	FL_UNSET(str, STR_ASSOC);
 | 
			
		||||
	RSTRING(str)->as.heap.aux.shared = shared;
 | 
			
		||||
	STR_SET_SHARED(str, shared);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	str_replace_shared(str, str2);
 | 
			
		||||
| 
						 | 
				
			
			@ -1447,7 +1453,7 @@ rb_str_associate(VALUE str, VALUE add)
 | 
			
		|||
	}
 | 
			
		||||
	FL_SET(str, STR_ASSOC);
 | 
			
		||||
	RBASIC_CLEAR_CLASS(add);
 | 
			
		||||
	RSTRING(str)->as.heap.aux.shared = add;
 | 
			
		||||
	OBJ_WRITE(str, &RSTRING(str)->as.heap.aux.shared, add);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -940,9 +940,11 @@ generic_ivar_set(VALUE obj, ID id, VALUE val)
 | 
			
		|||
	tbl = st_init_numtable();
 | 
			
		||||
	st_add_direct(generic_iv_tbl, (st_data_t)obj, (st_data_t)tbl);
 | 
			
		||||
	st_add_direct(tbl, (st_data_t)id, (st_data_t)val);
 | 
			
		||||
	if (FL_ABLE(obj)) OBJ_WRITTEN(obj, Qundef, val);
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
    st_insert((st_table *)data, (st_data_t)id, (st_data_t)val);
 | 
			
		||||
    if (FL_ABLE(obj)) OBJ_WRITTEN(obj, data, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
| 
						 | 
				
			
			@ -1181,12 +1183,13 @@ rb_ivar_set(VALUE obj, ID id, VALUE val)
 | 
			
		|||
                ROBJECT(obj)->as.heap.iv_index_tbl = iv_index_tbl;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        ROBJECT_IVPTR(obj)[index] = val;
 | 
			
		||||
        OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[index], val);
 | 
			
		||||
	break;
 | 
			
		||||
      case T_CLASS:
 | 
			
		||||
      case T_MODULE:
 | 
			
		||||
	if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable();
 | 
			
		||||
	st_insert(RCLASS_IV_TBL(obj), (st_data_t)id, val);
 | 
			
		||||
	OBJ_WRITTEN(obj, Qundef, val);
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
      generic:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -577,7 +577,7 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic, rb_call_info_t *ci, int is_attr)
 | 
			
		|||
	    VALUE *ptr = ROBJECT_IVPTR(obj);
 | 
			
		||||
 | 
			
		||||
	    if (index < len) {
 | 
			
		||||
		ptr[index] = val;
 | 
			
		||||
		OBJ_WRITE(obj, &ptr[index], val);
 | 
			
		||||
		return val; /* inline cache hit */
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue