From 6a1101f23ea403a8825c2f361508eeb85878b011 Mon Sep 17 00:00:00 2001 From: ko1 Date: Fri, 21 Jun 2013 11:22:18 +0000 Subject: [PATCH] * include/ruby/ruby.h: support write barrier protection for T_STRUCT. Introduce the following C APIs: * RSTRUCT_RAWPTR(st) returns pointer (do WB on your risk). The type of returned pointer is (const VALUE *). * RSTRUCT_GET(st, idx) returns idx-th value of struct. * RSTRUCT_SET(st, idx, v) set idx-th value by v with WB. And * RSTRUCT_PTR(st) returns pointer with shady operation. The type of returned pointer is (VALUE *). * struct.c, re.c, gc.c, marshal.c: rewrite with above APIs. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41534 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 14 +++++ gc.c | 4 +- include/ruby/ruby.h | 19 ++++--- marshal.c | 2 +- range.c | 17 +++--- struct.c | 126 +++++++++++++++++++++----------------------- 6 files changed, 102 insertions(+), 80 deletions(-) diff --git a/ChangeLog b/ChangeLog index 92a464ee60..27c74879eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Fri Jun 21 20:15:49 2013 Koichi Sasada + + * include/ruby/ruby.h: support write barrier protection for T_STRUCT. + Introduce the following C APIs: + * RSTRUCT_RAWPTR(st) returns pointer (do WB on your risk). + The type of returned pointer is (const VALUE *). + * RSTRUCT_GET(st, idx) returns idx-th value of struct. + * RSTRUCT_SET(st, idx, v) set idx-th value by v with WB. + And + * RSTRUCT_PTR(st) returns pointer with shady operation. + The type of returned pointer is (VALUE *). + + * struct.c, re.c, gc.c, marshal.c: rewrite with above APIs. + Fri Jun 21 19:38:37 2013 Tanaka Akira * bignum.c (BDIGMAX): Use BIGRAD. diff --git a/gc.c b/gc.c index bd0cc0272b..6527a814f1 100644 --- a/gc.c +++ b/gc.c @@ -1283,7 +1283,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) case T_STRUCT: if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 && RANY(obj)->as.rstruct.as.heap.ptr) { - xfree(RANY(obj)->as.rstruct.as.heap.ptr); + xfree((void *)RANY(obj)->as.rstruct.as.heap.ptr); } break; @@ -3386,7 +3386,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr) case T_STRUCT: { long len = RSTRUCT_LEN(obj); - VALUE *ptr = RSTRUCT_PTR(obj); + const VALUE *ptr = RSTRUCT_RAWPTR(obj); while (len--) { gc_mark(objspace, *ptr++); diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 32e7e196e7..f812e3146b 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -709,6 +709,9 @@ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type); #ifndef RGENGC_WB_PROTECTED_HASH #define RGENGC_WB_PROTECTED_HASH 1 #endif +#ifndef RGENGC_WB_PROTECTED_STRUCT +#define RGENGC_WB_PROTECTED_STRUCT 1 +#endif #ifndef RGENGC_WB_PROTECTED_STRING #define RGENGC_WB_PROTECTED_STRING 1 #endif @@ -1109,9 +1112,9 @@ struct RStruct { union { struct { long len; - VALUE *ptr; + const VALUE *ptr; } heap; - VALUE ary[RSTRUCT_EMBED_LEN_MAX]; + const VALUE ary[RSTRUCT_EMBED_LEN_MAX]; } as; }; #define RSTRUCT_EMBED_LEN_MASK (FL_USER2|FL_USER1) @@ -1121,11 +1124,15 @@ struct RStruct { (long)((RBASIC(st)->flags >> RSTRUCT_EMBED_LEN_SHIFT) & \ (RSTRUCT_EMBED_LEN_MASK >> RSTRUCT_EMBED_LEN_SHIFT)) : \ RSTRUCT(st)->as.heap.len) -#define RSTRUCT_PTR(st) \ - ((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? \ - RSTRUCT(st)->as.ary : \ - RSTRUCT(st)->as.heap.ptr) #define RSTRUCT_LENINT(st) rb_long2int(RSTRUCT_LEN(st)) +#define RSTRUCT_RAWPTR(st) \ + ((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? \ + RSTRUCT(st)->as.ary : \ + RSTRUCT(st)->as.heap.ptr) +#define RSTRUCT_PTR(st) ((VALUE *)RSTRUCT_RAWPTR(RGENGC_WB_PROTECTED_STRUCT ? OBJ_WB_GIVEUP((VALUE)st) : (VALUE)st)) + +#define RSTRUCT_SET(st, idx, v) OBJ_WRITE(st, (VALUE *)&RSTRUCT_RAWPTR(st)[idx], v) +#define RSTRUCT_GET(st, idx) (RSTRUCT_RAWPTR(st)[idx]) #define RBIGNUM_EMBED_LEN_MAX ((int)((sizeof(VALUE)*3)/sizeof(BDIGIT))) struct RBignum { diff --git a/marshal.c b/marshal.c index 9df02f310d..0884b7592c 100644 --- a/marshal.c +++ b/marshal.c @@ -821,7 +821,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) mem = rb_struct_members(obj); for (i=0; ias.ary[2]) #define EXCL(r) RTEST(RANGE_EXCL(r)) -#define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse) +static inline VALUE +SET_EXCL(VALUE r, VALUE v) +{ + RSTRUCT_SET(r, 2, v); + return v ? Qtrue : Qfalse; +} static VALUE range_failed(void) @@ -59,8 +64,8 @@ range_init(VALUE range, VALUE beg, VALUE end, int exclude_end) } SET_EXCL(range, exclude_end); - RSTRUCT(range)->as.ary[0] = beg; - RSTRUCT(range)->as.ary[1] = end; + RSTRUCT_SET(range, 0, beg); + RSTRUCT_SET(range, 1, end); } VALUE @@ -1228,9 +1233,9 @@ range_loader(VALUE range, VALUE obj) rb_raise(rb_eTypeError, "not a dumped range object"); } - RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg); - RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end); - RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl); + RSTRUCT_SET(range, 0, rb_ivar_get(obj, id_beg)); + RSTRUCT_SET(range, 1, rb_ivar_get(obj, id_end)); + RSTRUCT_SET(range, 2, rb_ivar_get(obj, id_excl)); return range; } diff --git a/struct.c b/struct.c index 4356f0013f..dbfd406f72 100644 --- a/struct.c +++ b/struct.c @@ -89,17 +89,15 @@ rb_struct_members_m(VALUE obj) VALUE rb_struct_getmember(VALUE obj, ID id) { - VALUE members, slot, *ptr, *ptr_members; + VALUE members, slot; long i, len; - ptr = RSTRUCT_PTR(obj); members = rb_struct_members(obj); - ptr_members = RARRAY_PTR(members); slot = ID2SYM(id); len = RARRAY_LEN(members); for (i=0; i argc) { - rb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc); + rb_mem_clear((VALUE *)RSTRUCT_RAWPTR(self)+argc, n-argc); } return Qnil; } @@ -414,18 +412,18 @@ static VALUE struct_alloc(VALUE klass) { long n; - NEWOBJ_OF(st, struct RStruct, klass, T_STRUCT); + NEWOBJ_OF(st, struct RStruct, klass, T_STRUCT | (RGENGC_WB_PROTECTED_STRUCT ? FL_WB_PROTECTED : 0)); n = num_members(klass); if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) { RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK; RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT; - rb_mem_clear(st->as.ary, n); + rb_mem_clear((VALUE *)st->as.ary, n); } else { st->as.heap.ptr = ALLOC_N(VALUE, n); - rb_mem_clear(st->as.heap.ptr, n); + rb_mem_clear((VALUE *)st->as.heap.ptr, n); st->as.heap.len = n; } @@ -488,7 +486,7 @@ rb_struct_each(VALUE s) RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size); for (i=0; i"); OBJ_INFECT(str, s); @@ -604,7 +600,7 @@ rb_struct_inspect(VALUE s) static VALUE rb_struct_to_a(VALUE s) { - return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s)); + return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_RAWPTR(s)); } /* @@ -626,7 +622,7 @@ rb_struct_to_h(VALUE s) long i; for (i=0; i