Feature #9889

Updated by Shyouhei Urabe 10 months ago

~~~Patch
From b042711f88b74c9b260a8a6d82d3e040174c01d2 Mon Sep 17 00:00:00 2001
From: "Urabe, Shyouhei" <shyouhei@ruby-lang.org>
Date: Sat, 31 May 2014 22:13:24 +0900
Subject: [PATCH] Hide Hash internal

I chose struct RHash for several reasons:



- I'm farmiliar with its internals so I'm 100% sure with this patch.

- At least Ko1, Eric, and myself think current hash implementation needs improvements. So hiding its internal is urgent.

- Hash is a relatively complex data strcture compared to Strings and Arrays, so its internals are seldom touched.

Signed-off-by: Urabe, Shyouhei <shyouhei@ruby-lang.org>
---
ChangeLog | 14 ++++++++++++++
hash.c | 29 ++++++++++++++++++++++++++---
include/ruby/intern.h | 3 +++
include/ruby/ruby.h | 13 +++----------
internal.h | 9 +++++++++
5 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8381daa..ea789cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Sat May 31 22:10:32 2014 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * include/ruby/ruby.h (struct RHash): no longer.
+
+ * internal.h (struct RHash): moved here.
+
+ * hash.c (rb_hash_ifnone): compatibilty accessor function.
+
+ * hash.c (rb_hash_iter_lev): ditto.
+
+ * hash.c (rb_hash_size_): ditto.
+
+ (note) rb_hash_size() already exists.
+
Sat May 31 21:15:43 2014 URABE Shyouhei <shyouhei@ruby-lang.org>

* thread.c (rb_thread_atfork_internal): My compiler complains
diff --git a/hash.c b/hash.c
index 93efde7..59f79a9 100644
--- a/hash.c
+++ b/hash.c
@@ -235,14 +235,14 @@ hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
static VALUE
hash_foreach_ensure_rollback(VALUE hash)
{
- RHASH_ITER_LEV(hash)++;
+ RHASH(hash)->iter_lev++;
return 0;
}

static VALUE
hash_foreach_ensure(VALUE hash)
{
- if (--RHASH_ITER_LEV(hash) == 0) {
+ if (--RHASH(hash)->iter_lev == 0) {
if (FL_TEST(hash, HASH_DELETED)) {
st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef);
FL_UNSET(hash, HASH_DELETED);
@@ -268,7 +268,7 @@ rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)

if (!RHASH(hash)->ntbl)
return;
- RHASH_ITER_LEV(hash)++;
+ RHASH(hash)->iter_lev++;
arg.hash = hash;
arg.func = (rb_foreach_func *)func;
arg.arg = farg;
@@ -354,6 +354,29 @@ rb_hash_tbl_raw(VALUE hash)
return hash_tbl(hash);
}

+VALUE
+rb_hash_ifnone(VALUE hash)
+{
+ return RHASH(hash)->ifnone;
+}
+
+int
+rb_hash_iter_lev(VALUE hash)
+{
+ return RHASH(hash)->iter_lev;
+}
+
+st_index_t
+rb_hash_size_(VALUE hash)
+{
+ if (RHASH(hash)->ntbl) {
+ return RHASH(hash)->ntbl->num_entries;
+ }
+ else {
+ return 0;
+ }
+}
+
static void
rb_hash_modify(VALUE hash)
{
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 387f000..4758533 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -503,6 +503,9 @@ 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);
+VALUE rb_hash_ifnone(VALUE);
+int rb_hash_iter_lev(VALUE);
+st_index_t rb_hash_size_(VALUE);
int rb_path_check(const char*);
int rb_env_path_tainted(void);
VALUE rb_env_clear(void);
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 7c7cb67..f033f46 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -924,17 +924,11 @@ struct RRegexp {
#define RREGEXP_SRC_LEN(r) RSTRING_LEN(RREGEXP(r)->src)
#define RREGEXP_SRC_END(r) RSTRING_END(RREGEXP(r)->src)

-struct RHash {
- struct RBasic basic;
- struct st_table *ntbl; /* possibly 0 */
- int iter_lev;
- const VALUE ifnone;
-};
/* RHASH_TBL allocates st_table if not available. */
#define RHASH_TBL(h) rb_hash_tbl(h)
-#define RHASH_ITER_LEV(h) (RHASH(h)->iter_lev)
-#define RHASH_IFNONE(h) (RHASH(h)->ifnone)
-#define RHASH_SIZE(h) (RHASH(h)->ntbl ? (st_index_t)RHASH(h)->ntbl->num_entries : 0)
+#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h)
+#define RHASH_IFNONE(h) rb_hash_ifnone(h)
+#define RHASH_SIZE(h) rb_hash_size_(h)
#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone)

@@ -1081,7 +1075,6 @@ struct RStruct {
#define RSTRING(obj) (R_CAST(RString)(obj))
#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
#define RARRAY(obj) (R_CAST(RArray)(obj))
-#define RHASH(obj) (R_CAST(RHash)(obj))
#define RDATA(obj) (R_CAST(RData)(obj))
#define RTYPEDDATA(obj) (R_CAST(RTypedData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
diff --git a/internal.h b/internal.h
index 2c1c6a3..854d9d9 100644
--- a/internal.h
+++ b/internal.h
@@ -420,6 +420,15 @@ struct RSymbol {

#define RSYMBOL(obj) (R_CAST(RSymbol)(obj))

+struct RHash {
+ struct RBasic basic;
+ struct st_table *ntbl; /* possibly 0 */
+ int iter_lev;
+ const VALUE ifnone;
+};
+
+#define RHASH(obj) (R_CAST(RHash)(obj))
+
/* class.c */
void rb_class_subclass_add(VALUE super, VALUE klass);
void rb_class_remove_from_super_subclasses(VALUE);
--
1.9.1
~~~

Back