mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 08:25:20 +08:00
Combine items, keys, collision_table in rb_id_table
This commit is contained in:
1 parent
aa30b60133
commit
14a257cfa3
3 files changed
+63
-45
Notes:
git
2026-08-27 11:58:11 +00:00
No files matched your search
+56
-33
@@ -31,20 +31,46 @@ id2key(ID id)
|
||||
ID is strictly 3 bits larger than rb_id_serial_t */
|
||||
|
||||
#if SIZEOF_VALUE == 8
|
||||
/* The table body is a single buffer laid out as:
|
||||
|
||||
[VALUE values[capa] | id_key_t keys[capa] | collision bitmap]
|
||||
|
||||
where the collision bitmap uses one mark bit per slot. Keeping the
|
||||
keys out of the item struct avoids padding them to the alignment of
|
||||
VALUE. The three regions are computed from buf and capa, so the
|
||||
struct only needs to store the buffer pointer. */
|
||||
#define COLLISION_TABLE_SIZE(capa) roomof((size_t)(capa), CHAR_BIT)
|
||||
#define ID_TABLE_ITEMS_SIZE(capa) \
|
||||
#define ID_TABLE_BUF_SIZE(capa) \
|
||||
((sizeof(VALUE) + sizeof(id_key_t)) * (size_t)(capa) + COLLISION_TABLE_SIZE(capa))
|
||||
|
||||
#define ITEM_GET_KEY(tbl, i) ((tbl)->keys[i])
|
||||
#define ITEM_KEY_ISSET(tbl, i) ((tbl)->items && (tbl)->keys[i])
|
||||
#define ITEM_COLLIDED(tbl, i) ((tbl)->collision_table[(i) / CHAR_BIT] & ((uint8_t)1 << ((i) % CHAR_BIT)))
|
||||
#define ITEM_SET_COLLIDED(tbl, i) ((tbl)->collision_table[(i) / CHAR_BIT] |= ((uint8_t)1 << ((i) % CHAR_BIT)))
|
||||
#define ITEM_VALUE(tbl, i) ((tbl)->items[i])
|
||||
static inline VALUE *
|
||||
id_table_items(struct rb_id_table *tbl)
|
||||
{
|
||||
return (VALUE *)tbl->buf;
|
||||
}
|
||||
|
||||
static inline id_key_t *
|
||||
id_table_keys(struct rb_id_table *tbl)
|
||||
{
|
||||
return (id_key_t *)(id_table_items(tbl) + tbl->capa);
|
||||
}
|
||||
|
||||
static inline uint8_t *
|
||||
id_table_collision_table(struct rb_id_table *tbl)
|
||||
{
|
||||
return (uint8_t *)(id_table_keys(tbl) + tbl->capa);
|
||||
}
|
||||
|
||||
#define ITEM_GET_KEY(tbl, i) (id_table_keys(tbl)[i])
|
||||
#define ITEM_KEY_ISSET(tbl, i) ((tbl)->buf && id_table_keys(tbl)[i])
|
||||
#define ITEM_COLLIDED(tbl, i) (id_table_collision_table(tbl)[(i) / CHAR_BIT] & ((uint8_t)1 << ((i) % CHAR_BIT)))
|
||||
#define ITEM_SET_COLLIDED(tbl, i) (id_table_collision_table(tbl)[(i) / CHAR_BIT] |= ((uint8_t)1 << ((i) % CHAR_BIT)))
|
||||
#define ITEM_VALUE(tbl, i) (id_table_items(tbl)[i])
|
||||
|
||||
static inline void
|
||||
ITEM_SET_KEY(struct rb_id_table *tbl, int i, id_key_t key)
|
||||
{
|
||||
tbl->keys[i] = key;
|
||||
id_table_keys(tbl)[i] = key;
|
||||
}
|
||||
#else
|
||||
typedef struct rb_id_item {
|
||||
@@ -52,18 +78,19 @@ typedef struct rb_id_item {
|
||||
VALUE val;
|
||||
} item_t;
|
||||
|
||||
#define ID_TABLE_ITEMS_SIZE(capa) (sizeof(item_t) * (size_t)(capa))
|
||||
#define ID_TABLE_BUF_SIZE(capa) (sizeof(item_t) * (size_t)(capa))
|
||||
#define id_table_items(tbl) ((item_t *)(tbl)->buf)
|
||||
|
||||
#define ITEM_GET_KEY(tbl, i) ((tbl)->items[i].key >> 1)
|
||||
#define ITEM_KEY_ISSET(tbl, i) ((tbl)->items[i].key > 1)
|
||||
#define ITEM_COLLIDED(tbl, i) ((tbl)->items[i].key & 1)
|
||||
#define ITEM_SET_COLLIDED(tbl, i) ((tbl)->items[i].key |= 1)
|
||||
#define ITEM_VALUE(tbl, i) ((tbl)->items[i].val)
|
||||
#define ITEM_GET_KEY(tbl, i) (id_table_items(tbl)[i].key >> 1)
|
||||
#define ITEM_KEY_ISSET(tbl, i) (id_table_items(tbl)[i].key > 1)
|
||||
#define ITEM_COLLIDED(tbl, i) (id_table_items(tbl)[i].key & 1)
|
||||
#define ITEM_SET_COLLIDED(tbl, i) (id_table_items(tbl)[i].key |= 1)
|
||||
#define ITEM_VALUE(tbl, i) (id_table_items(tbl)[i].val)
|
||||
|
||||
static inline void
|
||||
ITEM_SET_KEY(struct rb_id_table *tbl, int i, id_key_t key)
|
||||
{
|
||||
tbl->items[i].key = (key << 1) | ITEM_COLLIDED(tbl, i);
|
||||
id_table_items(tbl)[i].key = (key << 1) | ITEM_COLLIDED(tbl, i);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -81,15 +108,12 @@ round_capa(int capa)
|
||||
}
|
||||
|
||||
static void
|
||||
id_table_alloc_items(struct rb_id_table *tbl, int capa)
|
||||
id_table_alloc_buf(struct rb_id_table *tbl, int capa)
|
||||
{
|
||||
#if SIZEOF_VALUE == 8
|
||||
/* The values, keys, and collision bitmap share a single allocation. */
|
||||
tbl->items = ruby_xcalloc(1, ID_TABLE_ITEMS_SIZE(capa));
|
||||
tbl->keys = (id_key_t *)(tbl->items + capa);
|
||||
tbl->collision_table = (uint8_t *)(tbl->keys + capa);
|
||||
tbl->buf = ruby_xcalloc(1, ID_TABLE_BUF_SIZE(capa));
|
||||
#else
|
||||
tbl->items = ZALLOC_N(item_t, capa);
|
||||
tbl->buf = ZALLOC_N(item_t, capa);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -101,7 +125,7 @@ rb_id_table_init(struct rb_id_table *tbl, size_t s_capa)
|
||||
if (capa > 0) {
|
||||
capa = round_capa(capa);
|
||||
tbl->capa = (int)capa;
|
||||
id_table_alloc_items(tbl, capa);
|
||||
id_table_alloc_buf(tbl, capa);
|
||||
}
|
||||
return tbl;
|
||||
}
|
||||
@@ -116,13 +140,13 @@ rb_id_table_create(size_t capa)
|
||||
void
|
||||
rb_id_table_free_items(struct rb_id_table *tbl)
|
||||
{
|
||||
xfree(tbl->items);
|
||||
xfree(tbl->buf);
|
||||
}
|
||||
|
||||
void
|
||||
rb_id_table_free(struct rb_id_table *tbl)
|
||||
{
|
||||
xfree(tbl->items);
|
||||
xfree(tbl->buf);
|
||||
xfree(tbl);
|
||||
}
|
||||
|
||||
@@ -131,9 +155,8 @@ rb_id_table_clear(struct rb_id_table *tbl)
|
||||
{
|
||||
tbl->num = 0;
|
||||
tbl->used = 0;
|
||||
if (tbl->items) {
|
||||
/* Values, keys, and collision bitmap live in one allocation. */
|
||||
memset(tbl->items, 0, ID_TABLE_ITEMS_SIZE(tbl->capa));
|
||||
if (tbl->buf) {
|
||||
memset(tbl->buf, 0, ID_TABLE_BUF_SIZE(tbl->capa));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +169,7 @@ rb_id_table_size(const struct rb_id_table *tbl)
|
||||
size_t
|
||||
rb_id_table_memsize(const struct rb_id_table *tbl)
|
||||
{
|
||||
return ID_TABLE_ITEMS_SIZE(tbl->capa) + sizeof(struct rb_id_table);
|
||||
return ID_TABLE_BUF_SIZE(tbl->capa) + sizeof(struct rb_id_table);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -216,14 +239,14 @@ hash_table_extend(struct rb_id_table* tbl)
|
||||
new_cap = round_capa(tbl->used + (tbl->used >> 1));
|
||||
}
|
||||
tmp_tbl.capa = new_cap;
|
||||
id_table_alloc_items(&tmp_tbl, new_cap);
|
||||
id_table_alloc_buf(&tmp_tbl, new_cap);
|
||||
for (i = 0; i < tbl->capa; i++) {
|
||||
id_key_t key = ITEM_GET_KEY(tbl, i);
|
||||
if (key != 0) {
|
||||
hash_table_raw_insert(&tmp_tbl, key, ITEM_VALUE(tbl, i));
|
||||
}
|
||||
}
|
||||
old = tbl->items;
|
||||
old = tbl->buf;
|
||||
*tbl = tmp_tbl;
|
||||
xfree(old);
|
||||
}
|
||||
@@ -233,14 +256,14 @@ hash_table_extend(struct rb_id_table* tbl)
|
||||
static void
|
||||
hash_table_show(struct rb_id_table *tbl)
|
||||
{
|
||||
const id_key_t *keys = tbl->keys;
|
||||
const int capa = tbl->capa;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "tbl: %p (capa: %d, num: %d, used: %d)\n", tbl, tbl->capa, tbl->num, tbl->used);
|
||||
for (i=0; i<capa; i++) {
|
||||
if (ITEM_KEY_ISSET(tbl, i)) {
|
||||
fprintf(stderr, " -> [%d] %s %d\n", i, rb_id2name(key2id(keys[i])), (int)keys[i]);
|
||||
const id_key_t key = ITEM_GET_KEY(tbl, i);
|
||||
fprintf(stderr, " -> [%d] %s %d\n", i, rb_id2name(key2id(key)), (int)key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,7 +337,7 @@ rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_f
|
||||
{
|
||||
int i, capa = tbl->capa;
|
||||
|
||||
if (!tbl->items) {
|
||||
if (!tbl->buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -390,7 +413,7 @@ rb_managed_id_table_create(const rb_data_type_t *type, size_t capa)
|
||||
struct rb_id_table *tbl;
|
||||
VALUE obj = TypedData_Make_Struct(0, struct rb_id_table, type, tbl);
|
||||
RB_OBJ_SET_SHAREABLE(obj);
|
||||
rb_id_table_init(tbl, capa); // NOTE: this can cause GC, so dmark and dsize need to check tbl->items
|
||||
rb_id_table_init(tbl, capa); // NOTE: this can cause GC, so dmark and dsize need to check tbl->buf
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
+6
-11
@@ -4,21 +4,16 @@
|
||||
#include <stddef.h>
|
||||
#include "ruby/ruby.h"
|
||||
|
||||
#if SIZEOF_VALUE != 8
|
||||
struct rb_id_item;
|
||||
#endif
|
||||
|
||||
struct rb_id_table {
|
||||
int capa;
|
||||
int num;
|
||||
int used;
|
||||
#if SIZEOF_VALUE == 8
|
||||
VALUE *items;
|
||||
uint32_t *keys;
|
||||
uint8_t *collision_table;
|
||||
#else
|
||||
struct rb_id_item *items;
|
||||
#endif
|
||||
/* The table body is a single buffer laid out as:
|
||||
*
|
||||
* [VALUE values[capa] | id_key_t keys[capa] | collision bitmap]
|
||||
*
|
||||
* where the collision bitmap uses one mark bit per slot. */
|
||||
void *buf;
|
||||
};
|
||||
|
||||
/* compatible with ST_* */
|
||||
|
||||
Generated
+1
-1
@@ -410,7 +410,7 @@ pub type rb_atomic_t = ::std::os::raw::c_uint;
|
||||
#[repr(align(8))]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct rb_id_table {
|
||||
pub _bindgen_opaque_blob: [u64; 5usize],
|
||||
pub _bindgen_opaque_blob: [u64; 3usize],
|
||||
}
|
||||
pub const imemo_env: imemo_type = 0;
|
||||
pub const imemo_cref: imemo_type = 1;
|
||||
|
||||
Reference in new issue
Block a user