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

ruby-changes:28881

From: ko1 <ko1@a...>
Date: Sun, 26 May 2013 21:37:23 +0900 (JST)
Subject: [ruby-changes:28881] ko1:r40933 (trunk): * hash.c, include/ruby/ruby.h: support WB protected hash.

ko1	2013-05-26 21:37:11 +0900 (Sun, 26 May 2013)

  New Revision: 40933

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40933

  Log:
    * hash.c, include/ruby/ruby.h: support WB protected hash.
    * constify RHash::ifnone and make new macro RHASH_SET_IFNONE().
    * insert write barrier for st_update().
    * include/ruby/intern.h: declare rb_hash_set_ifnone(hash, ifnone).
    * marshal.c (r_object0): use RHASH_SET_IFNONE().
    * ext/openssl/ossl_x509name.c (Init_ossl_x509name): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/ext/openssl/ossl_x509name.c
    trunk/hash.c
    trunk/include/ruby/intern.h
    trunk/include/ruby/ruby.h
    trunk/marshal.c

Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 40932)
+++ include/ruby/intern.h	(revision 40933)
@@ -460,6 +460,7 @@ VALUE rb_hash_aset(VALUE, VALUE, VALUE); https://github.com/ruby/ruby/blob/trunk/include/ruby/intern.h#L460
 VALUE rb_hash_clear(VALUE);
 VALUE rb_hash_delete_if(VALUE);
 VALUE rb_hash_delete(VALUE,VALUE);
+VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone);
 typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value);
 VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func);
 struct st_table *rb_hash_tbl(VALUE);
Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 40932)
+++ include/ruby/ruby.h	(revision 40933)
@@ -689,6 +689,11 @@ VALUE rb_obj_setup(VALUE obj, VALUE klas https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L689
 #ifndef RGENGC_WB_PROTECTED_ARRAY
 #define RGENGC_WB_PROTECTED_ARRAY 1
 #endif
+
+#ifndef RGENGC_WB_PROTECTED_HASH
+#define RGENGC_WB_PROTECTED_HASH 1
+#endif
+
 #ifndef RGENGC_WB_PROTECTED_STRING
 #define RGENGC_WB_PROTECTED_STRING 1
 #endif
@@ -960,7 +965,7 @@ struct RHash { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L965
     struct RBasic basic;
     struct st_table *ntbl;      /* possibly 0 */
     int iter_lev;
-    VALUE ifnone;
+    const VALUE ifnone;
 };
 /* RHASH_TBL allocates st_table if not available. */
 #define RHASH_TBL(h) rb_hash_tbl(h)
@@ -968,6 +973,7 @@ struct RHash { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L973
 #define RHASH_IFNONE(h) (RHASH(h)->ifnone)
 #define RHASH_SIZE(h) (RHASH(h)->ntbl ? RHASH(h)->ntbl->num_entries : 0)
 #define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
+#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone)
 
 struct RFile {
     struct RBasic basic;
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 40932)
+++ ChangeLog	(revision 40933)
@@ -1,3 +1,15 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun May 26 21:31:46 2013  Koichi Sasada  <ko1@a...>
+
+	* hash.c, include/ruby/ruby.h: support WB protected hash.
+	  * constify RHash::ifnone and make new macro RHASH_SET_IFNONE().
+	  * insert write barrier for st_update().
+
+	* include/ruby/intern.h: declare rb_hash_set_ifnone(hash, ifnone).
+
+	* marshal.c (r_object0): use RHASH_SET_IFNONE().
+
+	* ext/openssl/ossl_x509name.c (Init_ossl_x509name): ditto.
+
 Sat May 25 23:22:38 2013  Kazuki Tsujimoto  <kazuki@c...>
 
 	* test/fiddle/test_c_struct_entry.rb,
Index: ext/openssl/ossl_x509name.c
===================================================================
--- ext/openssl/ossl_x509name.c	(revision 40932)
+++ ext/openssl/ossl_x509name.c	(revision 40933)
@@ -459,7 +459,7 @@ Init_ossl_x509name() https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_x509name.c#L459
      */
     rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
     hash = rb_hash_new();
-    RHASH(hash)->ifnone = utf8str;
+    RHASH_SET_IFNONE(hash, utf8str);
     rb_hash_aset(hash, rb_str_new2("C"), ptrstr);
     rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
     rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
Index: hash.c
===================================================================
--- hash.c	(revision 40932)
+++ hash.c	(revision 40933)
@@ -32,6 +32,16 @@ static VALUE rb_hash_s_try_convert(VALUE https://github.com/ruby/ruby/blob/trunk/hash.c#L32
 #define HASH_DELETED  FL_USER1
 #define HASH_PROC_DEFAULT FL_USER2
 
+/*
+ * Hash WB strategy:
+ *  1. Check mutate st_* functions
+ *     * st_insert()
+ *     * st_insert2()
+ *     * st_update()
+ *     * st_add_direct()
+ *  2. Insert WBs
+ */
+
 VALUE
 rb_hash_freeze(VALUE hash)
 {
@@ -43,6 +53,13 @@ VALUE rb_cHash; https://github.com/ruby/ruby/blob/trunk/hash.c#L53
 static VALUE envtbl;
 static ID id_hash, id_yield, id_default;
 
+VALUE
+rb_hash_set_ifnone(VALUE hash, VALUE ifnone)
+{
+    OBJ_WRITE(hash, (VALUE *)(&RHASH(hash)->ifnone), ifnone);
+    return hash;
+}
+
 static int
 rb_any_cmp(VALUE a, VALUE b)
 {
@@ -213,9 +230,9 @@ rb_hash_foreach(VALUE hash, int (*func)( https://github.com/ruby/ruby/blob/trunk/hash.c#L230
 static VALUE
 hash_alloc(VALUE klass)
 {
-    NEWOBJ_OF(hash, struct RHash, klass, T_HASH);
+    NEWOBJ_OF(hash, struct RHash, klass, T_HASH | (RGENGC_WB_PROTECTED_HASH ? FL_WB_PROTECTED : 0));
 
-    RHASH_IFNONE(hash) = Qnil;
+    RHASH_SET_IFNONE((VALUE)hash, Qnil);
 
     return (VALUE)hash;
 }
@@ -250,7 +267,7 @@ rb_hash_dup(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L267
     if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
         FL_SET(ret, HASH_PROC_DEFAULT);
     }
-    RHASH_IFNONE(ret) = RHASH_IFNONE(hash);
+    RHASH_SET_IFNONE(ret, RHASH_IFNONE(hash));
     return (VALUE)ret;
 }
 
@@ -262,8 +279,8 @@ rb_hash_modify_check(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L279
 	rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
 }
 
-struct st_table *
-rb_hash_tbl(VALUE hash)
+static struct st_table *
+hash_tbl(VALUE hash)
 {
     if (!RHASH(hash)->ntbl) {
         RHASH(hash)->ntbl = st_init_table(&objhash);
@@ -271,11 +288,18 @@ rb_hash_tbl(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L288
     return RHASH(hash)->ntbl;
 }
 
+struct st_table *
+rb_hash_tbl(VALUE hash)
+{
+    OBJ_WB_GIVEUP(hash);
+    return hash_tbl(hash);
+}
+
 static void
 rb_hash_modify(VALUE hash)
 {
     rb_hash_modify_check(hash);
-    rb_hash_tbl(hash);
+    hash_tbl(hash);
 }
 
 NORETURN(static void no_new_key(void));
@@ -285,20 +309,35 @@ no_new_key(void) https://github.com/ruby/ruby/blob/trunk/hash.c#L309
     rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
 }
 
-#define NOINSERT_UPDATE_CALLBACK(func) \
-int \
-func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
-{ \
-    if (!existing) no_new_key(); \
-    return func(key, val, arg, existing); \
-}
+struct update_callback_arg {
+    VALUE hash;
+    st_data_t arg;
+};
 
-#define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func)
+#define NOINSERT_UPDATE_CALLBACK(func)                                       \
+int                                                                          \
+func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
+{                                                                            \
+    struct update_callback_arg *uc_arg = (struct update_callback_arg *)arg;  \
+    if (!existing) no_new_key();                                             \
+    return func(uc_arg->hash, key, val, uc_arg->arg, existing);              \
+}                                                                            \
+int                                                                          \
+func##_insert(st_data_t *key, st_data_t *val, st_data_t arg, int existing)   \
+{                                                                            \
+    struct update_callback_arg *uc_arg = (struct update_callback_arg *)arg;  \
+    return func(uc_arg->hash, key, val, uc_arg->arg, existing);              \
+}
+
+#define UPDATE_CALLBACK(iter_lev, func) ((iter_lev) > 0 ? func##_noinsert : func##_insert)
+
+#define RHASH_UPDATE_ITER(h, iter_lev, key, func, a) do {                \
+    struct update_callback_arg uc_arg; uc_arg.hash = h; uc_arg.arg = a; \
+    st_update(RHASH(h)->ntbl, (st_data_t)(key),	                         \
+	      UPDATE_CALLBACK((iter_lev), func),	                 \
+	      (st_data_t)(&uc_arg));                                     \
+} while (0)
 
-#define RHASH_UPDATE_ITER(hash, iter_lev, key, func, arg) \
-    st_update(RHASH(hash)->ntbl, (st_data_t)(key),	  \
-	      UPDATE_CALLBACK((iter_lev), func),	  \
-	      (st_data_t)(arg))
 #define RHASH_UPDATE(hash, key, func, arg) \
     RHASH_UPDATE_ITER(hash, RHASH_ITER_LEV(hash), key, func, arg)
 
@@ -358,12 +397,12 @@ rb_hash_initialize(int argc, VALUE *argv https://github.com/ruby/ruby/blob/trunk/hash.c#L397
 	rb_check_arity(argc, 0, 0);
 	ifnone = rb_block_proc();
 	default_proc_arity_check(ifnone);
-	RHASH_IFNONE(hash) = ifnone;
+	RHASH_SET_IFNONE(hash, ifnone);
 	FL_SET(hash, HASH_PROC_DEFAULT);
     }
     else {
 	rb_scan_args(argc, argv, "01", &ifnone);
-	RHASH_IFNONE(hash) = ifnone;
+	RHASH_SET_IFNONE(hash, ifnone);
     }
 
     return hash;
@@ -709,7 +748,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/hash.c#L748
 rb_hash_set_default(VALUE hash, VALUE ifnone)
 {
     rb_hash_modify_check(hash);
-    RHASH_IFNONE(hash) = ifnone;
+    RHASH_SET_IFNONE(hash, ifnone);
     FL_UNSET(hash, HASH_PROC_DEFAULT);
     return ifnone;
 }
@@ -759,7 +798,7 @@ rb_hash_set_default_proc(VALUE hash, VAL https://github.com/ruby/ruby/blob/trunk/hash.c#L798
     rb_hash_modify_check(hash);
     if (NIL_P(proc)) {
 	FL_UNSET(hash, HASH_PROC_DEFAULT);
-	RHASH_IFNONE(hash) = proc;
+	RHASH_SET_IFNONE(hash, proc);
 	return proc;
     }
     b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
@@ -770,7 +809,7 @@ rb_hash_set_default_proc(VALUE hash, VAL https://github.com/ruby/ruby/blob/trunk/hash.c#L809
     }
     proc = b;
     default_proc_arity_check(proc);
-    RHASH_IFNONE(hash) = proc;
+    RHASH_SET_IFNONE(hash, proc);
     FL_SET(hash, HASH_PROC_DEFAULT);
     return proc;
 }
@@ -1146,17 +1185,17 @@ rb_hash_clear(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L1185
 }
 
 static int
-hash_aset(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
+hash_aset(VALUE hash, st_data_t *key, st_data_t *val, st_data_t arg, int existing)
 {
-    *val = arg;
+    OBJ_WRITE(hash, (VALUE *)val, arg);
     return ST_CONTINUE;
 }
 
 static int
-hash_aset_str(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
+hash_aset_str(VALUE hash, st_data_t *key, st_data_t *val, st_data_t arg, int existing)
 {
-    *key = (st_data_t)rb_str_new_frozen((VALUE)*key);
-    return hash_aset(key, val, arg, existing);
+    OBJ_WRITE(hash, (VALUE *)key, rb_str_new_frozen((VALUE)*key));
+    return hash_aset(hash, key, val, arg, existing);
 }
 
 static NOINSERT_UPDATE_CALLBACK(hash_aset)
@@ -1189,7 +1228,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALU https://github.com/ruby/ruby/blob/trunk/hash.c#L1228
     rb_hash_modify(hash);
     if (!tbl) {
 	if (iter_lev > 0) no_new_key();
-	tbl = RHASH_TBL(hash);
+	tbl = hash_tbl(hash);
     }
     if (tbl->type == &identhash || rb_obj_class(key) != rb_cString) {
 	RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
@@ -1227,7 +1266,7 @@ rb_hash_initialize_copy(VALUE hash, VALU https://github.com/ruby/ruby/blob/trunk/hash.c#L1266
     else {
 	FL_UNSET(hash, HASH_PROC_DEFAULT);
     }
-    RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);
+    RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
 
     return hash;
 }
@@ -1252,11 +1291,11 @@ rb_hash_replace(VALUE hash, VALUE hash2) https://github.com/ruby/ruby/blob/trunk/hash.c#L1291
     if (hash == hash2) return hash;
     rb_hash_clear(hash);
     if (RHASH(hash2)->ntbl) {
-	rb_hash_tbl(hash);
+	hash_tbl(hash);
 	RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type;
     }
     rb_hash_foreach(hash2, replace_i, hash);
-    RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);
+    RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
     if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
 	FL_SET(hash, HASH_PROC_DEFAULT);
     }
@@ -1525,7 +1564,7 @@ rb_hash_to_h(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L1564
 	if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
 	    FL_SET(ret, HASH_PROC_DEFAULT);
 	}
-	RHASH_IFNONE(ret) = RHASH_IFNONE(hash);
+	RHASH_SET_IFNONE(ret, RHASH_IFNONE(hash));
 	return ret;
     }
     return hash;
@@ -1832,9 +1871,9 @@ rb_hash_invert(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L1871
 }
 
 static int
-rb_hash_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+rb_hash_update_callback(VALUE hash, st_data_t *key, st_data_t *value, st_data_t arg, int existing)
 {
-    *value = arg;
+    OBJ_WRITE(hash, (VALUE *)value, (VALUE)arg);
     return ST_CONTINUE;
 }
 
@@ -1848,13 +1887,13 @@ rb_hash_update_i(VALUE key, VALUE value, https://github.com/ruby/ruby/blob/trunk/hash.c#L1887
 }
 
 static int
-rb_hash_update_block_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+rb_hash_update_block_callback(VALUE hash, st_data_t *key, st_data_t *value, st_data_t arg, int existing)
 {
     VALUE newvalue = (VALUE)arg;
     if (existing) {
 	newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue);
     }
-    *value = (st_data_t)newvalue;
+    OBJ_WRITE(hash, (VALUE *)value, newvalue);
     return ST_CONTINUE;
 }
 
@@ -1911,14 +1950,14 @@ struct update_arg { https://github.com/ruby/ruby/blob/trunk/hash.c#L1950
 };
 
 static int
-rb_hash_update_func_callback(st_data_t *key, st_data_t *value, st_data_t arg0, int existing)
+rb_hash_update_func_callback(VALUE hash, st_data_t *key, st_data_t *value, st_data_t arg0, int existing)
 {
     struct update_arg *arg = (struct update_arg *)arg0;
     VALUE newvalue = arg->value;
     if (existing) {
 	newvalue = (*arg->func)((VALUE)*key, (VALUE)*value, newvalue);
     }
-    *value = (st_data_t)newvalue;
+    OBJ_WRITE(hash, (VALUE *)value, (VALUE)newvalue);
     return ST_CONTINUE;
 }
 
@@ -1931,7 +1970,7 @@ rb_hash_update_func_i(VALUE key, VALUE v https://github.com/ruby/ruby/blob/trunk/hash.c#L1970
     VALUE hash = arg->hash;
 
     arg->value = value;
-    RHASH_UPDATE(hash, key, rb_hash_update_func_callback, arg);
+    RHASH_UPDATE(hash, key, rb_hash_update_func_callback, (VALUE)arg);
     return ST_CONTINUE;
 }
 
Index: marshal.c
===================================================================
--- marshal.c	(revision 40932)
+++ marshal.c	(revision 40933)
@@ -1725,7 +1725,7 @@ r_object0(struct load_arg *arg, int *ivp https://github.com/ruby/ruby/blob/trunk/marshal.c#L1725
 	    }
 	    arg->readable += 2;
 	    if (type == TYPE_HASH_DEF) {
-		RHASH_IFNONE(v) = r_object(arg);
+		RHASH_SET_IFNONE(v, r_object(arg));
 	    }
             v = r_leave(v, arg);
 	}

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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