mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40933 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ea54c59a8e
commit
a20a14727f
6 changed files with 99 additions and 41 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
Sun May 26 21:31:46 2013 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* 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@callcc.net>
|
Sat May 25 23:22:38 2013 Kazuki Tsujimoto <kazuki@callcc.net>
|
||||||
|
|
||||||
* test/fiddle/test_c_struct_entry.rb,
|
* test/fiddle/test_c_struct_entry.rb,
|
||||||
|
|
|
@ -459,7 +459,7 @@ Init_ossl_x509name()
|
||||||
*/
|
*/
|
||||||
rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
|
rb_define_const(cX509Name, "DEFAULT_OBJECT_TYPE", utf8str);
|
||||||
hash = rb_hash_new();
|
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("C"), ptrstr);
|
||||||
rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
|
rb_hash_aset(hash, rb_str_new2("countryName"), ptrstr);
|
||||||
rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
|
rb_hash_aset(hash, rb_str_new2("serialNumber"), ptrstr);
|
||||||
|
|
115
hash.c
115
hash.c
|
@ -32,6 +32,16 @@ static VALUE rb_hash_s_try_convert(VALUE, VALUE);
|
||||||
#define HASH_DELETED FL_USER1
|
#define HASH_DELETED FL_USER1
|
||||||
#define HASH_PROC_DEFAULT FL_USER2
|
#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
|
VALUE
|
||||||
rb_hash_freeze(VALUE hash)
|
rb_hash_freeze(VALUE hash)
|
||||||
{
|
{
|
||||||
|
@ -43,6 +53,13 @@ VALUE rb_cHash;
|
||||||
static VALUE envtbl;
|
static VALUE envtbl;
|
||||||
static ID id_hash, id_yield, id_default;
|
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
|
static int
|
||||||
rb_any_cmp(VALUE a, VALUE b)
|
rb_any_cmp(VALUE a, VALUE b)
|
||||||
{
|
{
|
||||||
|
@ -213,9 +230,9 @@ rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
|
||||||
static VALUE
|
static VALUE
|
||||||
hash_alloc(VALUE klass)
|
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;
|
return (VALUE)hash;
|
||||||
}
|
}
|
||||||
|
@ -250,7 +267,7 @@ rb_hash_dup(VALUE hash)
|
||||||
if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
|
if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
|
||||||
FL_SET(ret, 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;
|
return (VALUE)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +279,8 @@ rb_hash_modify_check(VALUE hash)
|
||||||
rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
|
rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct st_table *
|
static struct st_table *
|
||||||
rb_hash_tbl(VALUE hash)
|
hash_tbl(VALUE hash)
|
||||||
{
|
{
|
||||||
if (!RHASH(hash)->ntbl) {
|
if (!RHASH(hash)->ntbl) {
|
||||||
RHASH(hash)->ntbl = st_init_table(&objhash);
|
RHASH(hash)->ntbl = st_init_table(&objhash);
|
||||||
|
@ -271,11 +288,18 @@ rb_hash_tbl(VALUE hash)
|
||||||
return RHASH(hash)->ntbl;
|
return RHASH(hash)->ntbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct st_table *
|
||||||
|
rb_hash_tbl(VALUE hash)
|
||||||
|
{
|
||||||
|
OBJ_WB_GIVEUP(hash);
|
||||||
|
return hash_tbl(hash);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rb_hash_modify(VALUE hash)
|
rb_hash_modify(VALUE hash)
|
||||||
{
|
{
|
||||||
rb_hash_modify_check(hash);
|
rb_hash_modify_check(hash);
|
||||||
rb_hash_tbl(hash);
|
hash_tbl(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN(static void no_new_key(void));
|
NORETURN(static void no_new_key(void));
|
||||||
|
@ -285,20 +309,35 @@ no_new_key(void)
|
||||||
rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
|
rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NOINSERT_UPDATE_CALLBACK(func) \
|
struct update_callback_arg {
|
||||||
int \
|
VALUE hash;
|
||||||
|
st_data_t arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NOINSERT_UPDATE_CALLBACK(func) \
|
||||||
|
int \
|
||||||
func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
|
func##_noinsert(st_data_t *key, st_data_t *val, st_data_t arg, int existing) \
|
||||||
{ \
|
{ \
|
||||||
if (!existing) no_new_key(); \
|
struct update_callback_arg *uc_arg = (struct update_callback_arg *)arg; \
|
||||||
return func(key, val, arg, existing); \
|
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)
|
#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) \
|
#define RHASH_UPDATE(hash, key, func, arg) \
|
||||||
RHASH_UPDATE_ITER(hash, RHASH_ITER_LEV(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, VALUE hash)
|
||||||
rb_check_arity(argc, 0, 0);
|
rb_check_arity(argc, 0, 0);
|
||||||
ifnone = rb_block_proc();
|
ifnone = rb_block_proc();
|
||||||
default_proc_arity_check(ifnone);
|
default_proc_arity_check(ifnone);
|
||||||
RHASH_IFNONE(hash) = ifnone;
|
RHASH_SET_IFNONE(hash, ifnone);
|
||||||
FL_SET(hash, HASH_PROC_DEFAULT);
|
FL_SET(hash, HASH_PROC_DEFAULT);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_scan_args(argc, argv, "01", &ifnone);
|
rb_scan_args(argc, argv, "01", &ifnone);
|
||||||
RHASH_IFNONE(hash) = ifnone;
|
RHASH_SET_IFNONE(hash, ifnone);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
|
@ -709,7 +748,7 @@ static VALUE
|
||||||
rb_hash_set_default(VALUE hash, VALUE ifnone)
|
rb_hash_set_default(VALUE hash, VALUE ifnone)
|
||||||
{
|
{
|
||||||
rb_hash_modify_check(hash);
|
rb_hash_modify_check(hash);
|
||||||
RHASH_IFNONE(hash) = ifnone;
|
RHASH_SET_IFNONE(hash, ifnone);
|
||||||
FL_UNSET(hash, HASH_PROC_DEFAULT);
|
FL_UNSET(hash, HASH_PROC_DEFAULT);
|
||||||
return ifnone;
|
return ifnone;
|
||||||
}
|
}
|
||||||
|
@ -759,7 +798,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc)
|
||||||
rb_hash_modify_check(hash);
|
rb_hash_modify_check(hash);
|
||||||
if (NIL_P(proc)) {
|
if (NIL_P(proc)) {
|
||||||
FL_UNSET(hash, HASH_PROC_DEFAULT);
|
FL_UNSET(hash, HASH_PROC_DEFAULT);
|
||||||
RHASH_IFNONE(hash) = proc;
|
RHASH_SET_IFNONE(hash, proc);
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
||||||
|
@ -770,7 +809,7 @@ rb_hash_set_default_proc(VALUE hash, VALUE proc)
|
||||||
}
|
}
|
||||||
proc = b;
|
proc = b;
|
||||||
default_proc_arity_check(proc);
|
default_proc_arity_check(proc);
|
||||||
RHASH_IFNONE(hash) = proc;
|
RHASH_SET_IFNONE(hash, proc);
|
||||||
FL_SET(hash, HASH_PROC_DEFAULT);
|
FL_SET(hash, HASH_PROC_DEFAULT);
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
@ -1146,17 +1185,17 @@ rb_hash_clear(VALUE hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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);
|
OBJ_WRITE(hash, (VALUE *)key, rb_str_new_frozen((VALUE)*key));
|
||||||
return hash_aset(key, val, arg, existing);
|
return hash_aset(hash, key, val, arg, existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NOINSERT_UPDATE_CALLBACK(hash_aset)
|
static NOINSERT_UPDATE_CALLBACK(hash_aset)
|
||||||
|
@ -1189,7 +1228,7 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val)
|
||||||
rb_hash_modify(hash);
|
rb_hash_modify(hash);
|
||||||
if (!tbl) {
|
if (!tbl) {
|
||||||
if (iter_lev > 0) no_new_key();
|
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) {
|
if (tbl->type == &identhash || rb_obj_class(key) != rb_cString) {
|
||||||
RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
|
RHASH_UPDATE_ITER(hash, iter_lev, key, hash_aset, val);
|
||||||
|
@ -1227,7 +1266,7 @@ rb_hash_initialize_copy(VALUE hash, VALUE hash2)
|
||||||
else {
|
else {
|
||||||
FL_UNSET(hash, HASH_PROC_DEFAULT);
|
FL_UNSET(hash, HASH_PROC_DEFAULT);
|
||||||
}
|
}
|
||||||
RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);
|
RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
@ -1252,11 +1291,11 @@ rb_hash_replace(VALUE hash, VALUE hash2)
|
||||||
if (hash == hash2) return hash;
|
if (hash == hash2) return hash;
|
||||||
rb_hash_clear(hash);
|
rb_hash_clear(hash);
|
||||||
if (RHASH(hash2)->ntbl) {
|
if (RHASH(hash2)->ntbl) {
|
||||||
rb_hash_tbl(hash);
|
hash_tbl(hash);
|
||||||
RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type;
|
RHASH(hash)->ntbl->type = RHASH(hash2)->ntbl->type;
|
||||||
}
|
}
|
||||||
rb_hash_foreach(hash2, replace_i, hash);
|
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)) {
|
if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
|
||||||
FL_SET(hash, HASH_PROC_DEFAULT);
|
FL_SET(hash, HASH_PROC_DEFAULT);
|
||||||
}
|
}
|
||||||
|
@ -1525,7 +1564,7 @@ rb_hash_to_h(VALUE hash)
|
||||||
if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
|
if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
|
||||||
FL_SET(ret, 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 ret;
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
|
@ -1832,9 +1871,9 @@ rb_hash_invert(VALUE hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1848,13 +1887,13 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
VALUE newvalue = (VALUE)arg;
|
||||||
if (existing) {
|
if (existing) {
|
||||||
newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue);
|
newvalue = rb_yield_values(3, (VALUE)*key, (VALUE)*value, newvalue);
|
||||||
}
|
}
|
||||||
*value = (st_data_t)newvalue;
|
OBJ_WRITE(hash, (VALUE *)value, newvalue);
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1911,14 +1950,14 @@ struct update_arg {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
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;
|
struct update_arg *arg = (struct update_arg *)arg0;
|
||||||
VALUE newvalue = arg->value;
|
VALUE newvalue = arg->value;
|
||||||
if (existing) {
|
if (existing) {
|
||||||
newvalue = (*arg->func)((VALUE)*key, (VALUE)*value, newvalue);
|
newvalue = (*arg->func)((VALUE)*key, (VALUE)*value, newvalue);
|
||||||
}
|
}
|
||||||
*value = (st_data_t)newvalue;
|
OBJ_WRITE(hash, (VALUE *)value, (VALUE)newvalue);
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1931,7 +1970,7 @@ rb_hash_update_func_i(VALUE key, VALUE value, VALUE arg0)
|
||||||
VALUE hash = arg->hash;
|
VALUE hash = arg->hash;
|
||||||
|
|
||||||
arg->value = value;
|
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;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,6 +460,7 @@ VALUE rb_hash_aset(VALUE, VALUE, VALUE);
|
||||||
VALUE rb_hash_clear(VALUE);
|
VALUE rb_hash_clear(VALUE);
|
||||||
VALUE rb_hash_delete_if(VALUE);
|
VALUE rb_hash_delete_if(VALUE);
|
||||||
VALUE rb_hash_delete(VALUE,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);
|
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);
|
VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func);
|
||||||
struct st_table *rb_hash_tbl(VALUE);
|
struct st_table *rb_hash_tbl(VALUE);
|
||||||
|
|
|
@ -689,6 +689,11 @@ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
|
||||||
#ifndef RGENGC_WB_PROTECTED_ARRAY
|
#ifndef RGENGC_WB_PROTECTED_ARRAY
|
||||||
#define RGENGC_WB_PROTECTED_ARRAY 1
|
#define RGENGC_WB_PROTECTED_ARRAY 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef RGENGC_WB_PROTECTED_HASH
|
||||||
|
#define RGENGC_WB_PROTECTED_HASH 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef RGENGC_WB_PROTECTED_STRING
|
#ifndef RGENGC_WB_PROTECTED_STRING
|
||||||
#define RGENGC_WB_PROTECTED_STRING 1
|
#define RGENGC_WB_PROTECTED_STRING 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -960,7 +965,7 @@ struct RHash {
|
||||||
struct RBasic basic;
|
struct RBasic basic;
|
||||||
struct st_table *ntbl; /* possibly 0 */
|
struct st_table *ntbl; /* possibly 0 */
|
||||||
int iter_lev;
|
int iter_lev;
|
||||||
VALUE ifnone;
|
const VALUE ifnone;
|
||||||
};
|
};
|
||||||
/* RHASH_TBL allocates st_table if not available. */
|
/* RHASH_TBL allocates st_table if not available. */
|
||||||
#define RHASH_TBL(h) rb_hash_tbl(h)
|
#define RHASH_TBL(h) rb_hash_tbl(h)
|
||||||
|
@ -968,6 +973,7 @@ struct RHash {
|
||||||
#define RHASH_IFNONE(h) (RHASH(h)->ifnone)
|
#define RHASH_IFNONE(h) (RHASH(h)->ifnone)
|
||||||
#define RHASH_SIZE(h) (RHASH(h)->ntbl ? RHASH(h)->ntbl->num_entries : 0)
|
#define RHASH_SIZE(h) (RHASH(h)->ntbl ? RHASH(h)->ntbl->num_entries : 0)
|
||||||
#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 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 RFile {
|
||||||
struct RBasic basic;
|
struct RBasic basic;
|
||||||
|
|
|
@ -1725,7 +1725,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
|
||||||
}
|
}
|
||||||
arg->readable += 2;
|
arg->readable += 2;
|
||||||
if (type == TYPE_HASH_DEF) {
|
if (type == TYPE_HASH_DEF) {
|
||||||
RHASH_IFNONE(v) = r_object(arg);
|
RHASH_SET_IFNONE(v, r_object(arg));
|
||||||
}
|
}
|
||||||
v = r_leave(v, arg);
|
v = r_leave(v, arg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue