aboutsummaryrefslogtreecommitdiffstats
path: root/struct.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-21 11:22:18 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-06-21 11:22:18 +0000
commit6a1101f23ea403a8825c2f361508eeb85878b011 (patch)
tree89d04376f051f7aa2062fb9c1a46313b2ed22b49 /struct.c
parentc54a1abde3753fe94176ef959342a5972eae0e73 (diff)
downloadruby-6a1101f23ea403a8825c2f361508eeb85878b011.tar.gz
* 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
Diffstat (limited to 'struct.c')
-rw-r--r--struct.c126
1 files changed, 61 insertions, 65 deletions
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<len; i++) {
- if (ptr_members[i] == slot) {
- return ptr[i];
+ if (RARRAY_AREF(members, i) == slot) {
+ return RSTRUCT_GET(obj, i);
}
}
rb_name_error(id, "%s is not struct member", rb_id2name(id));
@@ -113,16 +111,16 @@ rb_struct_ref(VALUE obj)
return rb_struct_getmember(obj, rb_frame_this_func());
}
-static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_PTR(obj)[0];}
-static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_PTR(obj)[1];}
-static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_PTR(obj)[2];}
-static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_PTR(obj)[3];}
-static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_PTR(obj)[4];}
-static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_PTR(obj)[5];}
-static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_PTR(obj)[6];}
-static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_PTR(obj)[7];}
-static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_PTR(obj)[8];}
-static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_PTR(obj)[9];}
+static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
+static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
+static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
+static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
+static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
+static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
+static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
+static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
+static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
+static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
#define N_REF_FUNC numberof(ref_func)
@@ -149,18 +147,16 @@ rb_struct_modify(VALUE s)
static VALUE
rb_struct_set(VALUE obj, VALUE val)
{
- VALUE members, slot, *ptr, *ptr_members;
+ VALUE members, slot;
long i, len;
members = rb_struct_members(obj);
- ptr_members = RARRAY_PTR(members);
len = RARRAY_LEN(members);
rb_struct_modify(obj);
- ptr = RSTRUCT_PTR(obj);
for (i=0; i<len; i++) {
- slot = ptr_members[i];
+ slot = RARRAY_AREF(members, i);
if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
- return ptr[i] = val;
+ return RSTRUCT_SET(obj, i, val);
}
}
rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
@@ -390,16 +386,18 @@ static VALUE
rb_struct_initialize_m(int argc, VALUE *argv, VALUE self)
{
VALUE klass = rb_obj_class(self);
- long n;
+ long i, n;
rb_struct_modify(self);
n = num_members(klass);
if (n < argc) {
rb_raise(rb_eArgError, "struct size differs");
}
- MEMCPY(RSTRUCT_PTR(self), argv, VALUE, argc);
+ for (i=0; i<argc; i++) {
+ RSTRUCT_SET(self, i, argv[i]);
+ }
if (n > 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<RSTRUCT_LEN(s); i++) {
- rb_yield(RSTRUCT_PTR(s)[i]);
+ rb_yield(RSTRUCT_GET(s, i));
}
return s;
}
@@ -522,7 +520,7 @@ rb_struct_each_pair(VALUE s)
members = rb_struct_members(s);
for (i=0; i<RSTRUCT_LEN(s); i++) {
VALUE key = rb_ary_entry(members, i);
- VALUE value = RSTRUCT_PTR(s)[i];
+ VALUE value = RSTRUCT_GET(s, i);
rb_yield(rb_assoc_new(key, value));
}
return s;
@@ -533,7 +531,6 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
{
VALUE cname = rb_class_name(rb_obj_class(s));
VALUE members, str = rb_str_new2("#<struct ");
- VALUE *ptr, *ptr_members;
long i, len;
char first = RSTRING_PTR(cname)[0];
@@ -545,9 +542,8 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
}
members = rb_struct_members(s);
- ptr_members = RARRAY_PTR(members);
- ptr = RSTRUCT_PTR(s);
len = RSTRUCT_LEN(s);
+
for (i=0; i<len; i++) {
VALUE slot;
ID id;
@@ -558,7 +554,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
else if (first != '#') {
rb_str_cat2(str, " ");
}
- slot = ptr_members[i];
+ slot = RARRAY_AREF(members, i);
id = SYM2ID(slot);
if (rb_is_local_id(id) || rb_is_const_id(id)) {
rb_str_append(str, rb_id2str(id));
@@ -567,7 +563,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
rb_str_append(str, rb_inspect(slot));
}
rb_str_cat2(str, "=");
- rb_str_append(str, rb_inspect(ptr[i]));
+ rb_str_append(str, rb_inspect(RSTRUCT_GET(s, i)));
}
rb_str_cat2(str, ">");
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<RSTRUCT_LEN(s); i++) {
- rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
+ rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_GET(s, i));
}
return h;
}
@@ -635,11 +631,16 @@ rb_struct_to_h(VALUE s)
VALUE
rb_struct_init_copy(VALUE copy, VALUE s)
{
+ long i, len;
+
if (!OBJ_INIT_COPY(copy, s)) return copy;
if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
rb_raise(rb_eTypeError, "struct size mismatch");
}
- MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy));
+
+ for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
+ RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
+ }
return copy;
}
@@ -647,16 +648,12 @@ rb_struct_init_copy(VALUE copy, VALUE s)
static VALUE
rb_struct_aref_id(VALUE s, ID id)
{
- VALUE *ptr, members, *ptr_members;
- long i, len;
+ VALUE members = rb_struct_members(s);
+ long i, len = RARRAY_LEN(members);
- ptr = RSTRUCT_PTR(s);
- members = rb_struct_members(s);
- ptr_members = RARRAY_PTR(members);
- len = RARRAY_LEN(members);
for (i=0; i<len; i++) {
- if (SYM2ID(ptr_members[i]) == id) {
- return ptr[i];
+ if (SYM2ID(RARRAY_AREF(members, i)) == id) {
+ return RSTRUCT_GET(s, i);
}
}
rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
@@ -706,27 +703,24 @@ rb_struct_aref(VALUE s, VALUE idx)
if (RSTRUCT_LEN(s) <= i)
rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
i, RSTRUCT_LEN(s));
- return RSTRUCT_PTR(s)[i];
+ return RSTRUCT_GET(s, i);
}
static VALUE
rb_struct_aset_id(VALUE s, ID id, VALUE val)
{
- VALUE members, *ptr, *ptr_members;
- long i, len;
+ VALUE members = rb_struct_members(s);
+ long i, len = RARRAY_LEN(members);
- members = rb_struct_members(s);
- len = RARRAY_LEN(members);
- rb_struct_modify(s);
if (RSTRUCT_LEN(s) != len) {
rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
len, RSTRUCT_LEN(s));
}
- ptr = RSTRUCT_PTR(s);
- ptr_members = RARRAY_PTR(members);
+
for (i=0; i<len; i++) {
- if (SYM2ID(ptr_members[i]) == id) {
- ptr[i] = val;
+ if (SYM2ID(RARRAY_AREF(members, i)) == id) {
+ rb_struct_modify(s);
+ RSTRUCT_SET(s, i, val);
return val;
}
}
@@ -782,7 +776,8 @@ rb_struct_aset(VALUE s, VALUE idx, VALUE val)
i, RSTRUCT_LEN(s));
}
rb_struct_modify(s);
- return RSTRUCT_PTR(s)[i] = val;
+ RSTRUCT_SET(s, i, val);
+ return val;
}
static VALUE
@@ -835,8 +830,8 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
result = rb_ary_new();
for (i = 0; i < RSTRUCT_LEN(s); i++) {
- if (RTEST(rb_yield(RSTRUCT_PTR(s)[i]))) {
- rb_ary_push(result, RSTRUCT_PTR(s)[i]);
+ if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
+ rb_ary_push(result, RSTRUCT_GET(s, i));
}
}
@@ -846,12 +841,12 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
static VALUE
recursive_equal(VALUE s, VALUE s2, int recur)
{
- VALUE *ptr, *ptr2;
+ const VALUE *ptr, *ptr2;
long i, len;
if (recur) return Qtrue; /* Subtle! */
- ptr = RSTRUCT_PTR(s);
- ptr2 = RSTRUCT_PTR(s2);
+ ptr = RSTRUCT_RAWPTR(s);
+ ptr2 = RSTRUCT_RAWPTR(s2);
len = RSTRUCT_LEN(s);
for (i=0; i<len; i++) {
if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
@@ -892,11 +887,12 @@ recursive_hash(VALUE s, VALUE dummy, int recur)
{
long i, len;
st_index_t h;
- VALUE n, *ptr;
+ VALUE n;
+ const VALUE *ptr;
h = rb_hash_start(rb_hash(rb_obj_class(s)));
if (!recur) {
- ptr = RSTRUCT_PTR(s);
+ ptr = RSTRUCT_RAWPTR(s);
len = RSTRUCT_LEN(s);
for (i = 0; i < len; i++) {
n = rb_hash(ptr[i]);
@@ -923,12 +919,12 @@ rb_struct_hash(VALUE s)
static VALUE
recursive_eql(VALUE s, VALUE s2, int recur)
{
- VALUE *ptr, *ptr2;
+ const VALUE *ptr, *ptr2;
long i, len;
if (recur) return Qtrue; /* Subtle! */
- ptr = RSTRUCT_PTR(s);
- ptr2 = RSTRUCT_PTR(s2);
+ ptr = RSTRUCT_RAWPTR(s);
+ ptr2 = RSTRUCT_RAWPTR(s2);
len = RSTRUCT_LEN(s);
for (i=0; i<len; i++) {
if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;