[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]