Improve Hash table using variable sized segments.

parent 180b73fe
...@@ -18,7 +18,7 @@ MRB_BEGIN_DECL ...@@ -18,7 +18,7 @@ MRB_BEGIN_DECL
struct RHash { struct RHash {
MRB_OBJECT_HEADER; MRB_OBJECT_HEADER;
struct iv_tbl *iv; struct iv_tbl *iv;
struct seglist *ht; struct htable *ht;
}; };
#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) #define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v)))
......
...@@ -17,11 +17,12 @@ mrb_int mrb_float_id(mrb_float f); ...@@ -17,11 +17,12 @@ mrb_int mrb_float_id(mrb_float f);
#endif #endif
/* return non zero to break the loop */ /* return non zero to break the loop */
typedef int (sg_foreach_func)(mrb_state *mrb,mrb_value key, mrb_value val, void *data); typedef int (ht_foreach_func)(mrb_state *mrb,mrb_value key, mrb_value val, void *data);
#ifndef MRB_SG_SEGMENT_SIZE #ifndef MRB_HT_INIT_SIZE
#define MRB_SG_SEGMENT_SIZE 5 #define MRB_HT_INIT_SIZE 4
#endif #endif
#define HT_SEG_INCREASE_RATIO 1.2
struct segkv { struct segkv {
mrb_value key; mrb_value key;
...@@ -29,8 +30,9 @@ struct segkv { ...@@ -29,8 +30,9 @@ struct segkv {
}; };
typedef struct segment { typedef struct segment {
uint16_t size;
struct segment *next; struct segment *next;
struct segkv e[MRB_SG_SEGMENT_SIZE]; struct segkv e[];
} segment; } segment;
typedef struct segindex { typedef struct segindex {
...@@ -40,16 +42,16 @@ typedef struct segindex { ...@@ -40,16 +42,16 @@ typedef struct segindex {
} segindex; } segindex;
/* Instance variable table structure */ /* Instance variable table structure */
typedef struct seglist { typedef struct htable {
segment *rootseg; segment *rootseg;
segment *lastseg; segment *lastseg;
mrb_int size; mrb_int size;
mrb_int last_len; uint16_t last_len;
segindex *index; segindex *index;
} seglist; } htable;
static /* inline */ size_t static /* inline */ size_t
sg_hash_func(mrb_state *mrb, seglist *t, mrb_value key) ht_hash_func(mrb_state *mrb, htable *t, mrb_value key)
{ {
enum mrb_vtype tt = mrb_type(key); enum mrb_vtype tt = mrb_type(key);
mrb_value hv; mrb_value hv;
...@@ -84,7 +86,7 @@ sg_hash_func(mrb_state *mrb, seglist *t, mrb_value key) ...@@ -84,7 +86,7 @@ sg_hash_func(mrb_state *mrb, seglist *t, mrb_value key)
} }
static inline mrb_bool static inline mrb_bool
sg_hash_equal(mrb_state *mrb, seglist *t, mrb_value a, mrb_value b) ht_hash_equal(mrb_state *mrb, htable *t, mrb_value a, mrb_value b)
{ {
enum mrb_vtype tt = mrb_type(a); enum mrb_vtype tt = mrb_type(a);
...@@ -134,12 +136,12 @@ sg_hash_equal(mrb_state *mrb, seglist *t, mrb_value a, mrb_value b) ...@@ -134,12 +136,12 @@ sg_hash_equal(mrb_state *mrb, seglist *t, mrb_value a, mrb_value b)
} }
/* Creates the instance variable table. */ /* Creates the instance variable table. */
static seglist* static htable*
sg_new(mrb_state *mrb) ht_new(mrb_state *mrb)
{ {
seglist *t; htable *t;
t = (seglist*)mrb_malloc(mrb, sizeof(seglist)); t = (htable*)mrb_malloc(mrb, sizeof(htable));
t->size = 0; t->size = 0;
t->rootseg = NULL; t->rootseg = NULL;
t->lastseg = NULL; t->lastseg = NULL;
...@@ -163,11 +165,11 @@ sg_new(mrb_state *mrb) ...@@ -163,11 +165,11 @@ sg_new(mrb_state *mrb)
#define UPPER_BOUND(x) ((x)>>2|(x)>>1) #define UPPER_BOUND(x) ((x)>>2|(x)>>1)
#endif #endif
#define SG_MASK(index) ((index->capa)-1) #define HT_MASK(index) ((index->capa)-1)
/* Build index for the segment list */ /* Build index for the hash table */
static void static void
sg_index(mrb_state *mrb, seglist *t) ht_index(mrb_state *mrb, htable *t)
{ {
size_t size = (size_t)t->size; size_t size = (size_t)t->size;
size_t mask; size_t mask;
...@@ -175,14 +177,6 @@ sg_index(mrb_state *mrb, seglist *t) ...@@ -175,14 +177,6 @@ sg_index(mrb_state *mrb, seglist *t)
segment *seg; segment *seg;
size_t i; size_t i;
if (size < MRB_SG_SEGMENT_SIZE) {
if (index) {
failed:
mrb_free(mrb, index);
t->index = NULL;
}
return;
}
/* allocate index table */ /* allocate index table */
if (index && index->size >= UPPER_BOUND(index->capa)) { if (index && index->size >= UPPER_BOUND(index->capa)) {
size = index->capa+1; size = index->capa+1;
...@@ -190,7 +184,11 @@ sg_index(mrb_state *mrb, seglist *t) ...@@ -190,7 +184,11 @@ sg_index(mrb_state *mrb, seglist *t)
power2(size); power2(size);
if (!index || index->capa < size) { if (!index || index->capa < size) {
index = (segindex*)mrb_realloc_simple(mrb, index, sizeof(segindex)+sizeof(struct segkv*)*size); index = (segindex*)mrb_realloc_simple(mrb, index, sizeof(segindex)+sizeof(struct segkv*)*size);
if (index == NULL) goto failed; if (index == NULL) {
mrb_free(mrb, index);
t->index = NULL;
return;
}
t->index = index; t->index = index;
} }
index->size = t->size; index->size = t->size;
...@@ -200,10 +198,10 @@ sg_index(mrb_state *mrb, seglist *t) ...@@ -200,10 +198,10 @@ sg_index(mrb_state *mrb, seglist *t)
} }
/* rebuld index */ /* rebuld index */
mask = SG_MASK(index); mask = HT_MASK(index);
seg = t->rootseg; seg = t->rootseg;
while (seg) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
mrb_value key; mrb_value key;
size_t k, step = 0; size_t k, step = 0;
...@@ -212,7 +210,7 @@ sg_index(mrb_state *mrb, seglist *t) ...@@ -212,7 +210,7 @@ sg_index(mrb_state *mrb, seglist *t)
} }
key = seg->e[i].key; key = seg->e[i].key;
if (mrb_undef_p(key)) continue; if (mrb_undef_p(key)) continue;
k = sg_hash_func(mrb, t, key) & mask; k = ht_hash_func(mrb, t, key) & mask;
while (index->table[k]) { while (index->table[k]) {
k = (k+(++step)) & mask; k = (k+(++step)) & mask;
} }
...@@ -222,9 +220,9 @@ sg_index(mrb_state *mrb, seglist *t) ...@@ -222,9 +220,9 @@ sg_index(mrb_state *mrb, seglist *t)
} }
} }
/* Compacts the segment list removing deleted entries. */ /* Compacts the hash table removing deleted entries. */
static void static void
sg_compact(mrb_state *mrb, seglist *t) ht_compact(mrb_state *mrb, htable *t)
{ {
segment *seg; segment *seg;
mrb_int i; mrb_int i;
...@@ -235,11 +233,11 @@ sg_compact(mrb_state *mrb, seglist *t) ...@@ -235,11 +233,11 @@ sg_compact(mrb_state *mrb, seglist *t)
if (t == NULL) return; if (t == NULL) return;
seg = t->rootseg; seg = t->rootseg;
if (t->index && (size_t)t->size == t->index->size) { if (t->index && (size_t)t->size == t->index->size) {
sg_index(mrb, t); ht_index(mrb, t);
return; return;
} }
while (seg) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
mrb_value k = seg->e[i].key; mrb_value k = seg->e[i].key;
if (!seg->next && i >= t->last_len) { if (!seg->next && i >= t->last_len) {
...@@ -255,7 +253,7 @@ sg_compact(mrb_state *mrb, seglist *t) ...@@ -255,7 +253,7 @@ sg_compact(mrb_state *mrb, seglist *t)
size++; size++;
if (seg2 != NULL) { if (seg2 != NULL) {
seg2->e[i2++] = seg->e[i]; seg2->e[i2++] = seg->e[i];
if (i2 >= MRB_SG_SEGMENT_SIZE) { if (i2 >= seg2->size) {
seg2 = seg2->next; seg2 = seg2->next;
i2 = 0; i2 = 0;
} }
...@@ -279,13 +277,31 @@ sg_compact(mrb_state *mrb, seglist *t) ...@@ -279,13 +277,31 @@ sg_compact(mrb_state *mrb, seglist *t)
} }
} }
if (t->index) { if (t->index) {
sg_index(mrb, t); ht_index(mrb, t);
} }
} }
/* Set the value for the key in the indexed segment list. */ static segment*
segment_alloc(mrb_state *mrb, segment *seg)
{
uint32_t size;
if (!seg) size = MRB_HT_INIT_SIZE;
else {
size = seg->size*HT_SEG_INCREASE_RATIO + 1;
if (size > UINT16_MAX) size = UINT16_MAX;
}
seg = (segment*)mrb_malloc(mrb, sizeof(segment)+sizeof(struct segkv)*size);
seg->size = size;
seg->next = NULL;
return seg;
}
/* Set the value for the key in the indexed table. */
static void static void
sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) ht_index_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
{ {
segindex *index = t->index; segindex *index = t->index;
size_t k, sp, step = 0, mask; size_t k, sp, step = 0, mask;
...@@ -293,18 +309,18 @@ sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) ...@@ -293,18 +309,18 @@ sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val)
if (index->size >= UPPER_BOUND(index->capa)) { if (index->size >= UPPER_BOUND(index->capa)) {
/* need to expand table */ /* need to expand table */
sg_compact(mrb, t); ht_compact(mrb, t);
index = t->index; index = t->index;
} }
mask = SG_MASK(index); mask = HT_MASK(index);
sp = index->capa; sp = index->capa;
k = sg_hash_func(mrb, t, key) & mask; k = ht_hash_func(mrb, t, key) & mask;
while (index->table[k]) { while (index->table[k]) {
mrb_value key2 = index->table[k]->key; mrb_value key2 = index->table[k]->key;
if (mrb_undef_p(key2)) { if (mrb_undef_p(key2)) {
if (sp == index->capa) sp = k; if (sp == index->capa) sp = k;
} }
else if (sg_hash_equal(mrb, t, key, key2)) { else if (ht_hash_equal(mrb, t, key, key2)) {
index->table[k]->val = val; index->table[k]->val = val;
return; return;
} }
...@@ -316,11 +332,11 @@ sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) ...@@ -316,11 +332,11 @@ sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val)
/* put the value at the last */ /* put the value at the last */
seg = t->lastseg; seg = t->lastseg;
if (t->last_len < MRB_SG_SEGMENT_SIZE) { if (t->last_len < seg->size) {
index->table[k] = &seg->e[t->last_len++]; index->table[k] = &seg->e[t->last_len++];
} }
else { /* append a new segment */ else { /* append a new segment */
seg->next = (segment*)mrb_malloc(mrb, sizeof(segment)); seg->next = segment_alloc(mrb, seg);
seg = seg->next; seg = seg->next;
seg->next = NULL; seg->next = NULL;
t->lastseg = seg; t->lastseg = seg;
...@@ -333,21 +349,21 @@ sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) ...@@ -333,21 +349,21 @@ sg_index_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val)
t->size++; t->size++;
} }
/* Set the value for the key in the segment list. */ /* Set the value for the key in the table. */
static void static void
sg_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
{ {
segment *seg; segment *seg;
mrb_int i, deleted = 0; mrb_int i, deleted = 0;
if (t == NULL) return; if (t == NULL) return;
if (t->index) { if (t->index) {
sg_index_put(mrb, t, key, val); ht_index_put(mrb, t, key, val);
return; return;
} }
seg = t->rootseg; seg = t->rootseg;
while (seg) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
mrb_value k = seg->e[i].key; mrb_value k = seg->e[i].key;
/* Found room in last segment after last_len */ /* Found room in last segment after last_len */
if (!seg->next && i >= t->last_len) { if (!seg->next && i >= t->last_len) {
...@@ -361,25 +377,30 @@ sg_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) ...@@ -361,25 +377,30 @@ sg_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val)
deleted++; deleted++;
continue; continue;
} }
if (sg_hash_equal(mrb, t, k, key)) { if (ht_hash_equal(mrb, t, k, key)) {
seg->e[i].val = val; seg->e[i].val = val;
return; return;
} }
} }
seg = seg->next; seg = seg->next;
} }
/* Not found */ /* Not found */
if (deleted > MRB_SG_SEGMENT_SIZE) {
sg_compact(mrb, t); /* Compact if last segment has room */
if (deleted > 0 && deleted > MRB_HT_INIT_SIZE) {
ht_compact(mrb, t);
} }
t->size++; t->size++;
seg = (segment*)mrb_malloc(mrb, sizeof(segment)); /* check if thre's room after compaction */
seg->next = NULL; if (t->lastseg && t->last_len < t->lastseg->size) {
seg->e[0].key = key; seg = t->lastseg;
seg->e[0].val = val; i = t->last_len;
t->last_len = 1; }
else {
/* append new segment */
seg = segment_alloc(mrb, t->lastseg);
i = 0;
if (t->rootseg == NULL) { if (t->rootseg == NULL) {
t->rootseg = seg; t->rootseg = seg;
} }
...@@ -387,23 +408,27 @@ sg_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val) ...@@ -387,23 +408,27 @@ sg_put(mrb_state *mrb, seglist *t, mrb_value key, mrb_value val)
t->lastseg->next = seg; t->lastseg->next = seg;
} }
t->lastseg = seg; t->lastseg = seg;
if (t->index == NULL && t->size > MRB_SG_SEGMENT_SIZE*4) { }
sg_index(mrb, t); seg->e[i].key = key;
seg->e[i].val = val;
t->last_len = i+1;
if (t->index == NULL && t->size > MRB_HT_INIT_SIZE*4) {
ht_index(mrb, t);
} }
} }
/* Get a value for a key from the indexed segment list. */ /* Get a value for a key from the indexed table. */
static mrb_bool static mrb_bool
sg_index_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ht_index_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
{ {
segindex *index = t->index; segindex *index = t->index;
size_t mask = SG_MASK(index); size_t mask = HT_MASK(index);
size_t k = sg_hash_func(mrb, t, key) & mask; size_t k = ht_hash_func(mrb, t, key) & mask;
size_t step = 0; size_t step = 0;
while (index->table[k]) { while (index->table[k]) {
mrb_value key2 = index->table[k]->key; mrb_value key2 = index->table[k]->key;
if (!mrb_undef_p(key2) && sg_hash_equal(mrb, t, key, key2)) { if (!mrb_undef_p(key2) && ht_hash_equal(mrb, t, key, key2)) {
if (vp) *vp = index->table[k]->val; if (vp) *vp = index->table[k]->val;
return TRUE; return TRUE;
} }
...@@ -412,28 +437,28 @@ sg_index_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ...@@ -412,28 +437,28 @@ sg_index_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp)
return FALSE; return FALSE;
} }
/* Get a value for a key from the segment list. */ /* Get a value for a key from the hash table. */
static mrb_bool static mrb_bool
sg_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
{ {
segment *seg; segment *seg;
mrb_int i; mrb_int i;
if (t == NULL) return FALSE; if (t == NULL) return FALSE;
if (t->index) { if (t->index) {
return sg_index_get(mrb, t, key, vp); return ht_index_get(mrb, t, key, vp);
} }
seg = t->rootseg; seg = t->rootseg;
while (seg) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
mrb_value k = seg->e[i].key; mrb_value k = seg->e[i].key;
if (!seg->next && i >= t->last_len) { if (!seg->next && i >= t->last_len) {
return FALSE; return FALSE;
} }
if (mrb_undef_p(k)) continue; if (mrb_undef_p(k)) continue;
if (sg_hash_equal(mrb, t, k, key)) { if (ht_hash_equal(mrb, t, k, key)) {
if (vp) *vp = seg->e[i].val; if (vp) *vp = seg->e[i].val;
return TRUE; return TRUE;
} }
...@@ -446,7 +471,7 @@ sg_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ...@@ -446,7 +471,7 @@ sg_get(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp)
/* Deletes the value for the symbol from the instance variable table. */ /* Deletes the value for the symbol from the instance variable table. */
/* Deletion is done by overwriting keys by `undef`. */ /* Deletion is done by overwriting keys by `undef`. */
static mrb_bool static mrb_bool
sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ht_del(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
{ {
segment *seg; segment *seg;
mrb_int i; mrb_int i;
...@@ -454,7 +479,7 @@ sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ...@@ -454,7 +479,7 @@ sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp)
if (t == NULL) return FALSE; if (t == NULL) return FALSE;
seg = t->rootseg; seg = t->rootseg;
while (seg) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
mrb_value key2; mrb_value key2;
if (!seg->next && i >= t->last_len) { if (!seg->next && i >= t->last_len) {
...@@ -462,7 +487,7 @@ sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ...@@ -462,7 +487,7 @@ sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp)
return FALSE; return FALSE;
} }
key2 = seg->e[i].key; key2 = seg->e[i].key;
if (!mrb_undef_p(key2) && sg_hash_equal(mrb, t, key, key2)) { if (!mrb_undef_p(key2) && ht_hash_equal(mrb, t, key, key2)) {
if (vp) *vp = seg->e[i].val; if (vp) *vp = seg->e[i].val;
seg->e[i].key = mrb_undef_value(); seg->e[i].key = mrb_undef_value();
t->size--; t->size--;
...@@ -476,18 +501,15 @@ sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp) ...@@ -476,18 +501,15 @@ sg_del(mrb_state *mrb, seglist *t, mrb_value key, mrb_value *vp)
/* Iterates over the instance variable table. */ /* Iterates over the instance variable table. */
static void static void
sg_foreach(mrb_state *mrb, seglist *t, sg_foreach_func *func, void *p) ht_foreach(mrb_state *mrb, htable *t, ht_foreach_func *func, void *p)
{ {
segment *seg; segment *seg;
mrb_int i; mrb_int i;
if (t == NULL) return; if (t == NULL) return;
if (t->index && t->index->size-(size_t)t->size > MRB_SG_SEGMENT_SIZE) {
sg_compact(mrb, t);
}
seg = t->rootseg; seg = t->rootseg;
while (seg) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
/* no value in last segment after last_len */ /* no value in last segment after last_len */
if (!seg->next && i >= t->last_len) { if (!seg->next && i >= t->last_len) {
return; return;
...@@ -500,34 +522,26 @@ sg_foreach(mrb_state *mrb, seglist *t, sg_foreach_func *func, void *p) ...@@ -500,34 +522,26 @@ sg_foreach(mrb_state *mrb, seglist *t, sg_foreach_func *func, void *p)
} }
} }
/* Get the size of the instance variable table. */
static mrb_int
sg_size(mrb_state *mrb, seglist *t)
{
if (t == NULL) return 0;
return t->size;
}
/* Copy the instance variable table. */ /* Copy the instance variable table. */
static seglist* static htable*
sg_copy(mrb_state *mrb, seglist *t) ht_copy(mrb_state *mrb, htable *t)
{ {
segment *seg; segment *seg;
seglist *t2; htable *t2;
mrb_int i; mrb_int i;
seg = t->rootseg; seg = t->rootseg;
t2 = sg_new(mrb); t2 = ht_new(mrb);
while (seg != NULL) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
mrb_value key = seg->e[i].key; mrb_value key = seg->e[i].key;
mrb_value val = seg->e[i].val; mrb_value val = seg->e[i].val;
if ((seg->next == NULL) && (i >= t->last_len)) { if ((seg->next == NULL) && (i >= t->last_len)) {
return t2; return t2;
} }
sg_put(mrb, t2, key, val); ht_put(mrb, t2, key, val);
} }
seg = seg->next; seg = seg->next;
} }
...@@ -536,7 +550,7 @@ sg_copy(mrb_state *mrb, seglist *t) ...@@ -536,7 +550,7 @@ sg_copy(mrb_state *mrb, seglist *t)
/* Free memory of the instance variable table. */ /* Free memory of the instance variable table. */
static void static void
sg_free(mrb_state *mrb, seglist *t) ht_free(mrb_state *mrb, htable *t)
{ {
segment *seg; segment *seg;
...@@ -576,20 +590,20 @@ hash_mark_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p) ...@@ -576,20 +590,20 @@ hash_mark_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
void void
mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash) mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash)
{ {
sg_foreach(mrb, hash->ht, hash_mark_i, NULL); ht_foreach(mrb, hash->ht, hash_mark_i, NULL);
} }
size_t size_t
mrb_gc_mark_hash_size(mrb_state *mrb, struct RHash *hash) mrb_gc_mark_hash_size(mrb_state *mrb, struct RHash *hash)
{ {
if (!hash->ht) return 0; if (!hash->ht) return 0;
return sg_size(mrb, hash->ht)*2; return hash->ht->size*2;
} }
void void
mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash) mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash)
{ {
sg_free(mrb, hash->ht); ht_free(mrb, hash->ht);
} }
MRB_API mrb_value MRB_API mrb_value
...@@ -609,8 +623,8 @@ mrb_hash_new_capa(mrb_state *mrb, mrb_int capa) ...@@ -609,8 +623,8 @@ mrb_hash_new_capa(mrb_state *mrb, mrb_int capa)
struct RHash *h; struct RHash *h;
h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
/* preallocate segment list */ /* preallocate hash table */
h->ht = sg_new(mrb); h->ht = ht_new(mrb);
/* capacity ignored */ /* capacity ignored */
h->iv = 0; h->iv = 0;
return mrb_obj_value(h); return mrb_obj_value(h);
...@@ -624,7 +638,7 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self) ...@@ -624,7 +638,7 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
{ {
mrb_value orig; mrb_value orig;
struct RHash* copy; struct RHash* copy;
seglist *orig_h; htable *orig_h;
mrb_value ifnone, vret; mrb_value ifnone, vret;
mrb_get_args(mrb, "o", &orig); mrb_get_args(mrb, "o", &orig);
...@@ -635,7 +649,7 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self) ...@@ -635,7 +649,7 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
orig_h = RHASH_TBL(self); orig_h = RHASH_TBL(self);
copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
copy->ht = sg_copy(mrb, orig_h); copy->ht = ht_copy(mrb, orig_h);
if (MRB_RHASH_DEFAULT_P(self)) { if (MRB_RHASH_DEFAULT_P(self)) {
copy->flags |= MRB_HASH_DEFAULT; copy->flags |= MRB_HASH_DEFAULT;
...@@ -663,22 +677,22 @@ check_kdict_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data) ...@@ -663,22 +677,22 @@ check_kdict_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data)
void void
mrb_hash_check_kdict(mrb_state *mrb, mrb_value self) mrb_hash_check_kdict(mrb_state *mrb, mrb_value self)
{ {
seglist *sg; htable *t;
sg = RHASH_TBL(self); t = RHASH_TBL(self);
if (!sg || sg_size(mrb, sg) == 0) return; if (!t || t->size == 0) return;
sg_foreach(mrb, sg, check_kdict_i, NULL); ht_foreach(mrb, t, check_kdict_i, NULL);
} }
MRB_API mrb_value MRB_API mrb_value
mrb_hash_dup(mrb_state *mrb, mrb_value self) mrb_hash_dup(mrb_state *mrb, mrb_value self)
{ {
struct RHash* copy; struct RHash* copy;
seglist *orig_h; htable *orig_h;
orig_h = RHASH_TBL(self); orig_h = RHASH_TBL(self);
copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
copy->ht = orig_h ? sg_copy(mrb, orig_h) : NULL; copy->ht = orig_h ? ht_copy(mrb, orig_h) : NULL;
return mrb_obj_value(copy); return mrb_obj_value(copy);
} }
...@@ -688,7 +702,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) ...@@ -688,7 +702,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
mrb_value val; mrb_value val;
mrb_sym mid; mrb_sym mid;
if (sg_get(mrb, RHASH_TBL(hash), key, &val)) { if (ht_get(mrb, RHASH_TBL(hash), key, &val)) {
return val; return val;
} }
...@@ -705,7 +719,7 @@ mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) ...@@ -705,7 +719,7 @@ mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
{ {
mrb_value val; mrb_value val;
if (sg_get(mrb, RHASH_TBL(hash), key, &val)) { if (ht_get(mrb, RHASH_TBL(hash), key, &val)) {
return val; return val;
} }
/* not found */ /* not found */
...@@ -718,7 +732,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) ...@@ -718,7 +732,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
mrb_hash_modify(mrb, hash); mrb_hash_modify(mrb, hash);
key = KEY(key); key = KEY(key);
sg_put(mrb, RHASH_TBL(hash), key, val); ht_put(mrb, RHASH_TBL(hash), key, val);
mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key); mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key);
mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val); mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val);
return; return;
...@@ -744,7 +758,7 @@ mrb_hash_modify(mrb_state *mrb, mrb_value hash) ...@@ -744,7 +758,7 @@ mrb_hash_modify(mrb_state *mrb, mrb_value hash)
} }
if (!RHASH_TBL(hash)) { if (!RHASH_TBL(hash)) {
RHASH_TBL(hash) = sg_new(mrb); RHASH_TBL(hash) = ht_new(mrb);
} }
} }
...@@ -985,10 +999,10 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) ...@@ -985,10 +999,10 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
MRB_API mrb_value MRB_API mrb_value
mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
{ {
seglist *sg = RHASH_TBL(hash); htable *t = RHASH_TBL(hash);
mrb_value del_val; mrb_value del_val;
if (sg_del(mrb, sg, key, &del_val)) { if (ht_del(mrb, t, key, &del_val)) {
return del_val; return del_val;
} }
...@@ -1006,15 +1020,15 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self) ...@@ -1006,15 +1020,15 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self)
return mrb_hash_delete_key(mrb, self, key); return mrb_hash_delete_key(mrb, self, key);
} }
/* find first element in segment list, and remove it. */ /* find first element in a hash table, and remove it. */
static void static void
sg_shift(mrb_state *mrb, seglist *t, mrb_value *kp, mrb_value *vp) ht_shift(mrb_state *mrb, htable *t, mrb_value *kp, mrb_value *vp)
{ {
segment *seg = t->rootseg; segment *seg = t->rootseg;
mrb_int i; mrb_int i;
while (seg) { while (seg) {
for (i=0; i<MRB_SG_SEGMENT_SIZE; i++) { for (i=0; i<seg->size; i++) {
mrb_value key; mrb_value key;
if (!seg->next && i >= t->last_len) { if (!seg->next && i >= t->last_len) {
...@@ -1050,13 +1064,13 @@ sg_shift(mrb_state *mrb, seglist *t, mrb_value *kp, mrb_value *vp) ...@@ -1050,13 +1064,13 @@ sg_shift(mrb_state *mrb, seglist *t, mrb_value *kp, mrb_value *vp)
static mrb_value static mrb_value
mrb_hash_shift(mrb_state *mrb, mrb_value hash) mrb_hash_shift(mrb_state *mrb, mrb_value hash)
{ {
seglist *sg = RHASH_TBL(hash); htable *t = RHASH_TBL(hash);
mrb_hash_modify(mrb, hash); mrb_hash_modify(mrb, hash);
if (sg && sg_size(mrb, sg) > 0) { if (t && t->size > 0) {
mrb_value del_key, del_val; mrb_value del_key, del_val;
sg_shift(mrb, sg, &del_key, &del_val); ht_shift(mrb, t, &del_key, &del_val);
mrb_gc_protect(mrb, del_key); mrb_gc_protect(mrb, del_key);
mrb_gc_protect(mrb, del_val); mrb_gc_protect(mrb, del_val);
return mrb_assoc_new(mrb, del_key, del_val); return mrb_assoc_new(mrb, del_key, del_val);
...@@ -1088,11 +1102,11 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash) ...@@ -1088,11 +1102,11 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash)
MRB_API mrb_value MRB_API mrb_value
mrb_hash_clear(mrb_state *mrb, mrb_value hash) mrb_hash_clear(mrb_state *mrb, mrb_value hash)
{ {
seglist *sg = RHASH_TBL(hash); htable *t = RHASH_TBL(hash);
mrb_hash_modify(mrb, hash); mrb_hash_modify(mrb, hash);
if (sg) { if (t) {
sg_free(mrb, sg); ht_free(mrb, t);
RHASH_TBL(hash) = NULL; RHASH_TBL(hash) = NULL;
} }
return hash; return hash;
...@@ -1144,19 +1158,19 @@ mrb_hash_aset(mrb_state *mrb, mrb_value self) ...@@ -1144,19 +1158,19 @@ mrb_hash_aset(mrb_state *mrb, mrb_value self)
static mrb_value static mrb_value
mrb_hash_size_m(mrb_state *mrb, mrb_value self) mrb_hash_size_m(mrb_state *mrb, mrb_value self)
{ {
seglist *sg = RHASH_TBL(self); htable *t = RHASH_TBL(self);
if (!sg) return mrb_fixnum_value(0); if (!t) return mrb_fixnum_value(0);
return mrb_fixnum_value(sg_size(mrb, sg)); return mrb_fixnum_value(t->size);
} }
MRB_API mrb_bool MRB_API mrb_bool
mrb_hash_empty_p(mrb_state *mrb, mrb_value self) mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
{ {
seglist *sg = RHASH_TBL(self); htable *t = RHASH_TBL(self);
if (!sg) return TRUE; if (!t) return TRUE;
return sg_size(mrb, sg) == 0; return t->size == 0;
} }
/* 15.2.13.4.12 */ /* 15.2.13.4.12 */
...@@ -1212,14 +1226,14 @@ hash_keys_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p) ...@@ -1212,14 +1226,14 @@ hash_keys_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
MRB_API mrb_value MRB_API mrb_value
mrb_hash_keys(mrb_state *mrb, mrb_value hash) mrb_hash_keys(mrb_state *mrb, mrb_value hash)
{ {
seglist *sg = RHASH_TBL(hash); htable *t = RHASH_TBL(hash);
size_t size; mrb_int size;
mrb_value ary; mrb_value ary;
if (!sg || (size = sg_size(mrb, sg)) == 0) if (!t || (size = t->size) == 0)
return mrb_ary_new(mrb); return mrb_ary_new(mrb);
ary = mrb_ary_new_capa(mrb, size); ary = mrb_ary_new_capa(mrb, size);
sg_foreach(mrb, sg, hash_keys_i, (void*)&ary); ht_foreach(mrb, t, hash_keys_i, (void*)&ary);
return ary; return ary;
} }
...@@ -1246,14 +1260,14 @@ hash_vals_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p) ...@@ -1246,14 +1260,14 @@ hash_vals_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
MRB_API mrb_value MRB_API mrb_value
mrb_hash_values(mrb_state *mrb, mrb_value hash) mrb_hash_values(mrb_state *mrb, mrb_value hash)
{ {
seglist *sg = RHASH_TBL(hash); htable *t = RHASH_TBL(hash);
size_t size; mrb_int size;
mrb_value ary; mrb_value ary;
if (!sg || (size = sg_size(mrb, sg)) == 0) if (!t || (size = t->size) == 0)
return mrb_ary_new(mrb); return mrb_ary_new(mrb);
ary = mrb_ary_new_capa(mrb, size); ary = mrb_ary_new_capa(mrb, size);
sg_foreach(mrb, sg, hash_vals_i, (void*)&ary); ht_foreach(mrb, t, hash_vals_i, (void*)&ary);
return ary; return ary;
} }
...@@ -1279,10 +1293,10 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash) ...@@ -1279,10 +1293,10 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash)
MRB_API mrb_bool MRB_API mrb_bool
mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key) mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key)
{ {
seglist *sg; htable *t;
sg = RHASH_TBL(hash); t = RHASH_TBL(hash);
if (sg_get(mrb, sg, key, NULL)) { if (ht_get(mrb, t, key, NULL)) {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
...@@ -1340,23 +1354,23 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash) ...@@ -1340,23 +1354,23 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
mrb_get_args(mrb, "o", &val); mrb_get_args(mrb, "o", &val);
arg.found = FALSE; arg.found = FALSE;
arg.val = val; arg.val = val;
sg_foreach(mrb, RHASH_TBL(hash), hash_has_value_i, &arg); ht_foreach(mrb, RHASH_TBL(hash), hash_has_value_i, &arg);
return mrb_bool_value(arg.found); return mrb_bool_value(arg.found);
} }
static int static int
merge_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data) merge_i(mrb_state *mrb, mrb_value key, mrb_value val, void *data)
{ {
seglist *h1 = (seglist*)data; htable *h1 = (htable*)data;
sg_put(mrb, h1, key, val); ht_put(mrb, h1, key, val);
return 0; return 0;
} }
MRB_API void MRB_API void
mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2) mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2)
{ {
seglist *h1, *h2; htable *h1, *h2;
mrb_hash_modify(mrb, hash1); mrb_hash_modify(mrb, hash1);
hash2 = mrb_ensure_hash_type(mrb, hash2); hash2 = mrb_ensure_hash_type(mrb, hash2);
...@@ -1365,10 +1379,10 @@ mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2) ...@@ -1365,10 +1379,10 @@ mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2)
if (!h2) return; if (!h2) return;
if (!h1) { if (!h1) {
RHASH_TBL(hash1) = sg_copy(mrb, h2); RHASH_TBL(hash1) = ht_copy(mrb, h2);
return; return;
} }
sg_foreach(mrb, h2, merge_i, h1); ht_foreach(mrb, h2, merge_i, h1);
mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash1)); mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash1));
return; return;
} }
...@@ -1389,7 +1403,7 @@ mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2) ...@@ -1389,7 +1403,7 @@ mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2)
static mrb_value static mrb_value
mrb_hash_rehash(mrb_state *mrb, mrb_value self) mrb_hash_rehash(mrb_state *mrb, mrb_value self)
{ {
sg_compact(mrb, RHASH_TBL(self)); ht_compact(mrb, RHASH_TBL(self));
return self; return self;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment