summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2023-04-19 16:02:36 -0400
committerPeter Zhu <peter@peterzhu.ca>2023-05-17 09:19:40 -0400
commit0938964ba1af3924cf969fb809fc3598892bc20d (patch)
treec87a84dcbec890a0e35a4a84c96a0892653dbbc0 /hash.c
parent5199f2aaf9527c97e6ec371e19748d0c2ac7a70e (diff)
Implement Hash ST tables on VWA
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/7742
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c110
1 files changed, 39 insertions, 71 deletions
diff --git a/hash.c b/hash.c
index f4aeee36c6..cef784cccc 100644
--- a/hash.c
+++ b/hash.c
@@ -378,27 +378,6 @@ typedef st_index_t st_hash_t;
#define RHASH_AR_TABLE_REF(hash, n) (&RHASH_AR_TABLE(hash)->pairs[n])
#define RHASH_AR_CLEARED_HINT 0xff
-typedef struct ar_table_pair_struct {
- VALUE key;
- VALUE val;
-} ar_table_pair;
-
-typedef struct ar_table_struct {
- /* 64bit CPU: 8B * 2 * 8 = 128B */
- ar_table_pair pairs[RHASH_AR_TABLE_MAX_SIZE];
-} ar_table;
-
-#define RHASH_EMBED_SIZE (offsetof(struct RHash, as.st) + sizeof(ar_table))
-
-size_t
-rb_hash_size_as_embedded(VALUE hash)
-{
- if (RHASH_AR_TABLE_P(hash)) {
- return RHASH_EMBED_SIZE;
- }
- return sizeof(struct RHash);
-}
-
static inline st_hash_t
ar_do_hash(st_data_t key)
{
@@ -539,6 +518,7 @@ hash_verify_(VALUE hash, const char *file, int line)
HASH_ASSERT(RHASH_AR_TABLE_SIZE_RAW(hash) == 0);
HASH_ASSERT(RHASH_AR_TABLE_BOUND_RAW(hash) == 0);
}
+
return hash;
}
@@ -564,25 +544,25 @@ RHASH_TABLE_EMPTY_P(VALUE hash)
return RHASH_SIZE(hash) == 0;
}
+#define RHASH_SET_ST_FLAG(h) FL_SET_RAW(h, RHASH_ST_TABLE_FLAG)
+#define RHASH_UNSET_ST_FLAG(h) FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG)
+
+static void
+hash_st_table_init(VALUE hash, const struct st_hash_type *type, st_index_t size)
+{
+ st_init_existing_table_with_size(RHASH_ST_TABLE(hash), type, size);
+ RHASH_SET_ST_FLAG(hash);
+}
+
void
rb_hash_st_table_set(VALUE hash, st_table *st)
{
HASH_ASSERT(st != NULL);
- FL_SET_RAW((hash), RHASH_ST_TABLE_FLAG);
- RHASH(hash)->as.st = st;
-}
+ RHASH_SET_ST_FLAG(hash);
-static void
-hash_ar_table_set(VALUE hash, ar_table *ar)
-{
- HASH_ASSERT(RHASH_AR_TABLE_P(hash));
- *(RHASH_AR_TABLE(hash)) = *ar;
- hash_verify(hash);
+ *RHASH_ST_TABLE(hash) = *st;
}
-#define RHASH_SET_ST_FLAG(h) FL_SET_RAW(h, RHASH_ST_TABLE_FLAG)
-#define RHASH_UNSET_ST_FLAG(h) FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG)
-
static inline void
RHASH_AR_TABLE_BOUND_SET(VALUE h, st_index_t n)
{
@@ -646,9 +626,6 @@ ar_alloc_table(VALUE hash)
ar_table *tab = RHASH_AR_TABLE(hash);
memset(tab, 0, sizeof(ar_table));
- // RHASH_UNSET_ST_FLAG(hash);
- // hash_ar_table_set(hash, tab);
-
RHASH_AR_TABLE_SIZE_SET(hash, 0);
RHASH_AR_TABLE_BOUND_SET(hash, 0);
@@ -730,28 +707,29 @@ ar_try_convert_table(VALUE hash)
const unsigned size = RHASH_AR_TABLE_SIZE(hash);
- st_table *new_tab;
- st_index_t i;
-
if (size < RHASH_AR_TABLE_MAX_SIZE) {
return;
}
- new_tab = st_init_table_with_size(&objhash, size * 2);
+ st_table tab;
+ st_table *new_tab = &tab;
+ rb_st_init_existing_table_with_size(new_tab, &objhash, size * 2);
- for (i = 0; i < RHASH_AR_TABLE_MAX_BOUND; i++) {
+ for (st_index_t i = 0; i < RHASH_AR_TABLE_MAX_BOUND; i++) {
ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
st_add_direct(new_tab, pair->key, pair->val);
}
+
ar_free_and_clear_table(hash);
RHASH_ST_TABLE_SET(hash, new_tab);
- return;
}
static st_table *
ar_force_convert_table(VALUE hash, const char *file, int line)
{
st_table *new_tab;
+ st_table tab;
+ new_tab = &tab;
if (RHASH_ST_TABLE_P(hash)) {
return RHASH_ST_TABLE(hash);
@@ -760,13 +738,7 @@ ar_force_convert_table(VALUE hash, const char *file, int line)
if (RHASH_AR_TABLE(hash)) {
unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
-#if defined(RHASH_CONVERT_TABLE_DEBUG) && RHASH_CONVERT_TABLE_DEBUG
- rb_obj_info_dump(hash);
- fprintf(stderr, "force_convert: %s:%d\n", file, line);
- RB_DEBUG_COUNTER_INC(obj_hash_force_convert);
-#endif
-
- new_tab = st_init_table_with_size(&objhash, RHASH_AR_TABLE_SIZE(hash));
+ rb_st_init_existing_table_with_size(new_tab, &objhash, RHASH_AR_TABLE_SIZE(hash));
for (i = 0; i < bound; i++) {
if (ar_cleared_entry(hash, i)) continue;
@@ -777,10 +749,13 @@ ar_force_convert_table(VALUE hash, const char *file, int line)
ar_free_and_clear_table(hash);
}
else {
- new_tab = st_init_table(&objhash);
+ rb_st_init_existing_table_with_size(new_tab, &objhash, 0);
}
+
RHASH_ST_TABLE_SET(hash, new_tab);
+ new_tab = RHASH_ST_TABLE(hash);
+
return new_tab;
}
@@ -1193,7 +1168,6 @@ ar_copy(VALUE hash1, VALUE hash2)
RHASH(hash1)->ar_hint.word = RHASH(hash2)->ar_hint.word;
RHASH_AR_TABLE_BOUND_SET(hash1, RHASH_AR_TABLE_BOUND(hash2));
RHASH_AR_TABLE_SIZE_SET(hash1, RHASH_AR_TABLE_SIZE(hash2));
- hash_ar_table_set(hash1, new_tab);
rb_gc_writebarrier_remember(hash1);
@@ -1454,7 +1428,7 @@ static VALUE
hash_alloc_flags(VALUE klass, VALUE flags, VALUE ifnone)
{
const VALUE wb = (RGENGC_WB_PROTECTED_HASH ? FL_WB_PROTECTED : 0);
- NEWOBJ_OF(hash, struct RHash, klass, T_HASH | wb | flags, RHASH_EMBED_SIZE, 0);
+ NEWOBJ_OF(hash, struct RHash, klass, T_HASH | wb | flags, RHASH_SLOT_SIZE, 0);
RHASH_SET_IFNONE((VALUE)hash, ifnone);
@@ -1498,7 +1472,7 @@ rb_hash_new_with_size(st_index_t size)
/* do nothing */
}
else if (size > RHASH_AR_TABLE_MAX_SIZE) {
- RHASH_ST_TABLE_SET(ret, st_init_table_with_size(&objhash, size));
+ hash_st_table_init(ret, &objhash, size);
}
return ret;
}
@@ -1981,10 +1955,12 @@ rb_hash_rehash(VALUE hash)
else if (RHASH_ST_TABLE_P(hash)) {
st_table *old_tab = RHASH_ST_TABLE(hash);
tmp = hash_alloc(0);
- tbl = st_init_table_with_size(old_tab->type, old_tab->num_entries);
- RHASH_ST_TABLE_SET(tmp, tbl);
+
+ hash_st_table_init(tmp, old_tab->type, old_tab->num_entries);
+ tbl = RHASH_ST_TABLE(tmp);
+
rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
- st_free_table(old_tab);
+
RHASH_ST_TABLE_SET(hash, tbl);
RHASH_ST_CLEAR(tmp);
}
@@ -2925,13 +2901,12 @@ rb_hash_replace(VALUE hash, VALUE hash2)
ar_free_and_clear_table(hash);
}
else {
- st_free_table(RHASH_ST_TABLE(hash));
RHASH_ST_CLEAR(hash);
}
hash_copy(hash, hash2);
if (RHASH_EMPTY_P(hash2) && RHASH_ST_TABLE_P(hash2)) {
/* ident hash */
- RHASH_ST_TABLE_SET(hash, st_init_table_with_size(RHASH_TYPE(hash2), 0));
+ hash_st_table_init(hash, RHASH_TYPE(hash2), 0);
}
rb_gc_writebarrier_remember(hash);
@@ -4306,8 +4281,6 @@ rb_hash_compact_bang(VALUE hash)
return Qnil;
}
-static st_table *rb_init_identtable_with_size(st_index_t size);
-
/*
* call-seq:
* hash.compare_by_identity -> self
@@ -4349,10 +4322,11 @@ rb_hash_compare_by_id(VALUE hash)
HASH_ASSERT(RHASH_ST_TABLE_P(hash));
tmp = hash_alloc(0);
- identtable = rb_init_identtable_with_size(RHASH_SIZE(hash));
- RHASH_ST_TABLE_SET(tmp, identtable);
+ hash_st_table_init(tmp, &identhash, RHASH_SIZE(hash));
+ identtable = RHASH_ST_TABLE(tmp);
+
rb_hash_foreach(hash, rb_hash_rehash_i, (VALUE)tmp);
- st_free_table(RHASH_ST_TABLE(hash));
+
RHASH_ST_TABLE_SET(hash, identtable);
RHASH_ST_CLEAR(tmp);
@@ -4376,7 +4350,7 @@ VALUE
rb_ident_hash_new(void)
{
VALUE hash = rb_hash_new();
- RHASH_ST_TABLE_SET(hash, st_init_table(&identhash));
+ hash_st_table_init(hash, &identhash, 0);
return hash;
}
@@ -4384,7 +4358,7 @@ VALUE
rb_ident_hash_new_with_size(st_index_t size)
{
VALUE hash = rb_hash_new();
- RHASH_ST_TABLE_SET(hash, st_init_table_with_size(&identhash, size));
+ hash_st_table_init(hash, &identhash, size);
return hash;
}
@@ -4394,12 +4368,6 @@ rb_init_identtable(void)
return st_init_table(&identhash);
}
-static st_table *
-rb_init_identtable_with_size(st_index_t size)
-{
- return st_init_table_with_size(&identhash, size);
-}
-
static int
any_p_i(VALUE key, VALUE value, VALUE arg)
{