ruby-changes:28651
From: ko1 <ko1@a...>
Date: Tue, 14 May 2013 03:08:07 +0900 (JST)
Subject: [ruby-changes:28651] ko1:r40703 (trunk): * gc.c: support RGENGC. [ruby-trunk - Feature #8339]
ko1 2013-05-14 03:07:47 +0900 (Tue, 14 May 2013) New Revision: 40703 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40703 Log: * 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. Modified files: trunk/ChangeLog trunk/array.c trunk/bignum.c trunk/complex.c trunk/debug.c trunk/gc.c trunk/include/ruby/ruby.h trunk/internal.h trunk/marshal.c trunk/node.h trunk/numeric.c trunk/object.c trunk/random.c trunk/range.c trunk/rational.c trunk/string.c trunk/variable.c trunk/vm_insnhelper.c Index: complex.c =================================================================== --- complex.c (revision 40702) +++ complex.c (revision 40703) @@ -313,7 +313,7 @@ k_complex_p(VALUE x) https://github.com/ruby/ruby/blob/trunk/complex.c#L313 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); Index: array.c =================================================================== --- array.c (revision 40702) +++ array.c (revision 40703) @@ -128,10 +128,12 @@ memfill(register VALUE *mem, register lo https://github.com/ruby/ruby/blob/trunk/array.c#L128 #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 a https://github.com/ruby/ruby/blob/trunk/array.c#L372 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) https://github.com/ruby/ruby/blob/trunk/array.c#L411 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) https://github.com/ruby/ruby/blob/trunk/array.c#L465 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) https://github.com/ruby/ruby/blob/trunk/array.c#L524 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, https://github.com/ruby/ruby/blob/trunk/array.c#L661 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, https://github.com/ruby/ruby/blob/trunk/array.c#L702 } } 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; Index: debug.c =================================================================== --- debug.c (revision 40702) +++ debug.c (revision 40703) @@ -32,8 +32,8 @@ const union { https://github.com/ruby/ruby/blob/trunk/debug.c#L32 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, Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 40702) +++ include/ruby/ruby.h (revision 40703) @@ -681,6 +681,32 @@ VALUE rb_obj_setup(VALUE obj, VALUE klas https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L681 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 { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L917 (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 { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L979 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 { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L988 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 { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1152 #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 { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1186 #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 { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L1207 #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)) Index: ChangeLog =================================================================== --- ChangeLog (revision 40702) +++ ChangeLog (revision 40703) @@ -1,3 +1,49 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue May 14 02:47:30 2013 Koichi Sasada <ko1@a...> + + * 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@a...> * gc.c: remove rb_objspace_t::marked_num. Index: variable.c =================================================================== --- variable.c (revision 40702) +++ variable.c (revision 40703) @@ -940,9 +940,11 @@ generic_ivar_set(VALUE obj, ID id, VALUE https://github.com/ruby/ruby/blob/trunk/variable.c#L940 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) https://github.com/ruby/ruby/blob/trunk/variable.c#L1183 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: Index: string.c =================================================================== --- string.c (revision 40702) +++ string.c (revision 40703) @@ -68,7 +68,6 @@ VALUE rb_cSymbol; https://github.com/ruby/ruby/blob/trunk/string.c#L68 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; https://github.com/ruby/ruby/blob/trunk/string.c#L118 }\ } 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) https://github.com/ruby/ruby/blob/trunk/string.c#L379 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 str https://github.com/ruby/ruby/blob/trunk/string.c#L653 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) https://github.com/ruby/ruby/blob/trunk/string.c#L702 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) https://github.com/ruby/ruby/blob/trunk/string.c#L721 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) https://github.com/ruby/ruby/blob/trunk/string.c#L746 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 s https://github.com/ruby/ruby/blob/trunk/string.c#L883 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) https://github.com/ruby/ruby/blob/trunk/string.c#L931 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) https://github.com/ruby/ruby/blob/trunk/string.c#L1453 } 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); } } Index: object.c =================================================================== --- object.c (revision 40702) +++ object.c (revision 40703) @@ -1800,7 +1800,7 @@ rb_obj_alloc(VALUE klass) https://github.com/ruby/ruby/blob/trunk/object.c#L1800 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; } Index: range.c =================================================================== --- range.c (revision 40702) +++ range.c (revision 40703) @@ -1211,7 +1211,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/range.c#L1211 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; Index: gc.c =================================================================== --- gc.c (revision 40702) +++ gc (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/