From 1b36b5d2ff702df5f6bd7c1a8bc19633fc9ad244 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Tue, 16 Sep 2014 16:44:44 +0900 Subject: [PATCH] update xhash (orderd map) --- codegen.c | 7 +-- dict.c | 30 ++++----- gc.c | 35 +++++------ include/picrin/xhash.h | 138 ++++++++++++++++++++++------------------- lib.c | 23 +++---- state.c | 7 +-- write.c | 10 ++- 7 files changed, 123 insertions(+), 127 deletions(-) diff --git a/codegen.c b/codegen.c index d9238456..34505723 100644 --- a/codegen.c +++ b/codegen.c @@ -62,7 +62,7 @@ static analyze_state * new_analyze_state(pic_state *pic) { analyze_state *state; - xh_iter it; + xh_entry *it; state = pic_alloc(pic, sizeof(analyze_state)); state->pic = pic; @@ -98,9 +98,8 @@ new_analyze_state(pic_state *pic) /* push initial scope */ push_scope(state, pic_nil_value()); - xh_begin(&it, &pic->globals); - while (xh_next(&it)) { - pic_sym sym = xh_key(it.e, pic_sym); + for (it = xh_begin(&pic->globals); it != NULL; it = xh_next(it)) { + pic_sym sym = xh_key(it, pic_sym); xv_push(&state->scope->locals, &sym); } diff --git a/dict.c b/dict.c index 4fc23c7a..229b55ad 100644 --- a/dict.c +++ b/dict.c @@ -222,13 +222,12 @@ pic_dict_dictionary_map(pic_state *pic) struct pic_proc *proc; struct pic_dict *dict; pic_value item, list = pic_nil_value(); - xh_iter it; + xh_entry *it; pic_get_args(pic, "ld", &proc, &dict); - xh_begin(&it, &dict->hash); - while (xh_next(&it)) { - item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value)); + for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) { + item = pic_cons(pic, xh_key(it, pic_value), xh_val(it, pic_value)); pic_push(pic, pic_apply1(pic, proc, item), list); } @@ -241,15 +240,14 @@ pic_dict_dictionary_for_each(pic_state *pic) struct pic_proc *proc; struct pic_dict *dict; pic_value item; - xh_iter it; + xh_entry *it; pic_get_args(pic, "ld", &proc, &dict); - xh_begin(&it, &dict->hash); - while (xh_next(&it)) { + for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) { int ai = pic_gc_arena_preserve(pic); - item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value)); + item = pic_cons(pic, xh_key(it, pic_value), xh_val(it, pic_value)); pic_apply1(pic, proc, item); pic_gc_arena_restore(pic, ai); @@ -263,13 +261,12 @@ pic_dict_dictionary_to_alist(pic_state *pic) { struct pic_dict *dict; pic_value item, alist = pic_nil_value(); - xh_iter it; + xh_entry *it; pic_get_args(pic, "d", &dict); - xh_begin(&it, &dict->hash); - while (xh_next(&it)) { - item = pic_cons(pic, xh_key(it.e, pic_value), xh_val(it.e, pic_value)); + for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) { + item = pic_cons(pic, xh_key(it, pic_value), xh_val(it, pic_value)); pic_push(pic, item, alist); } @@ -298,14 +295,13 @@ pic_dict_dictionary_to_plist(pic_state *pic) { struct pic_dict *dict; pic_value plist = pic_nil_value(); - xh_iter it; + xh_entry *it; pic_get_args(pic, "d", &dict); - xh_begin(&it, &dict->hash); - while (xh_next(&it)) { - pic_push(pic, xh_key(it.e, pic_value), plist); - pic_push(pic, xh_val(it.e, pic_value), plist); + for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) { + pic_push(pic, xh_key(it, pic_value), plist); + pic_push(pic, xh_val(it, pic_value), plist); } return pic_reverse(pic, plist); diff --git a/gc.c b/gc.c index 2d61be7f..ba0e23d7 100644 --- a/gc.c +++ b/gc.c @@ -475,32 +475,29 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) } case PIC_TT_DATA: { struct pic_data *data = (struct pic_data *)obj; - xh_iter it; + xh_entry *it; - xh_begin(&it, &data->storage); - while (xh_next(&it)) { - gc_mark(pic, xh_val(it.e, pic_value)); + for (it = xh_begin(&data->storage); it != NULL; it = xh_next(it)) { + gc_mark(pic, xh_val(it, pic_value)); } break; } case PIC_TT_DICT: { struct pic_dict *dict = (struct pic_dict *)obj; - xh_iter it; + xh_entry *it; - xh_begin(&it, &dict->hash); - while (xh_next(&it)) { - gc_mark(pic, xh_key(it.e, pic_value)); - gc_mark(pic, xh_val(it.e, pic_value)); + for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) { + gc_mark(pic, xh_key(it, pic_value)); + gc_mark(pic, xh_val(it, pic_value)); } break; } case PIC_TT_RECORD: { struct pic_record *rec = (struct pic_record *)obj; - xh_iter it; + xh_entry *it; - xh_begin(&it, &rec->hash); - while (xh_next(&it)) { - gc_mark(pic, xh_val(it.e, pic_value)); + for (it = xh_begin(&rec->hash); it != NULL; it = xh_next(it)) { + gc_mark(pic, xh_val(it, pic_value)); } break; } @@ -563,7 +560,7 @@ gc_mark_phase(pic_state *pic) pic_value *stack; pic_callinfo *ci; size_t i, j; - xh_iter it; + xh_entry *it; /* block */ if (pic->blk) { @@ -593,15 +590,13 @@ gc_mark_phase(pic_state *pic) } /* global variables */ - xh_begin(&it, &pic->globals); - while (xh_next(&it)) { - gc_mark(pic, xh_val(it.e, pic_value)); + for (it = xh_begin(&pic->globals); it != NULL; it = xh_next(it)) { + gc_mark(pic, xh_val(it, pic_value)); } /* macro objects */ - xh_begin(&it, &pic->macros); - while (xh_next(&it)) { - gc_mark_object(pic, xh_val(it.e, struct pic_object *)); + for (it = xh_begin(&pic->macros); it != NULL; it = xh_next(it)) { + gc_mark_object(pic, xh_val(it, struct pic_object *)); } /* error handlers */ diff --git a/include/picrin/xhash.h b/include/picrin/xhash.h index a249e2ff..c78dc118 100644 --- a/include/picrin/xhash.h +++ b/include/picrin/xhash.h @@ -1,5 +1,5 @@ -#ifndef XHASH_H__ -#define XHASH_H__ +#ifndef XHASH_H +#define XHASH_H /* * Copyright (c) 2013-2014 by Yuichi Nishiwaki @@ -27,6 +27,7 @@ extern "C" { typedef struct xh_entry { struct xh_entry *next; int hash; + struct xh_entry *fw, *bw; const char *key; /* == val + XHASH_ALIGN(vwidth) */ char val[]; } xh_entry; @@ -42,15 +43,16 @@ typedef struct xhash { size_t size, count, kwidth, vwidth; xh_hashf hashf; xh_equalf equalf; + xh_entry *chain; void *data; } xhash; -static inline void xh_init_(xhash *x, size_t, size_t, xh_hashf, xh_equalf, void *); -static inline xh_entry *xh_get_(xhash *x, const void *key); -static inline xh_entry *xh_put_(xhash *x, const void *key, void *val); -static inline void xh_del_(xhash *x, const void *key); -static inline void xh_clear(xhash *x); -static inline void xh_destroy(xhash *x); +/** Protected Methods: + * static inline void xh_init_(xhash *x, size_t, size_t, xh_hashf, xh_equalf, void *); + * static inline xh_entry *xh_get_(xhash *x, const void *key); + * static inline xh_entry *xh_put_(xhash *x, const void *key, void *val); + * static inline void xh_del_(xhash *x, const void *key); + */ /* string map */ static inline void xh_init_str(xhash *x, size_t width); @@ -70,14 +72,12 @@ static inline xh_entry *xh_get_int(xhash *x, int key); static inline xh_entry *xh_put_int(xhash *x, int key, void *); static inline void xh_del_int(xhash *x, int key); -typedef struct xh_iter { - xhash *x; - xh_entry *e, *next; - size_t bidx; -} xh_iter; +static inline size_t xh_size(xhash *x); +static inline void xh_clear(xhash *x); +static inline void xh_destroy(xhash *x); -static inline void xh_begin(xh_iter *it, xhash *x); -static inline int xh_next(xh_iter *it); +static inline xh_entry *xh_begin(xhash *x); +static inline xh_entry *xh_next(xh_entry *e); static inline void @@ -98,6 +98,7 @@ xh_init_(xhash *x, size_t kwidth, size_t vwidth, xh_hashf hashf, xh_equalf equal x->vwidth = vwidth; x->hashf = hashf; x->equalf = equalf; + x->chain = NULL; x->data = data; xh_bucket_realloc(x, XHASH_INIT_SIZE); @@ -123,21 +124,22 @@ static inline void xh_resize_(xhash *x, size_t newsize) { xhash y; - xh_iter it; + xh_entry *it; size_t idx; xh_init_(&y, x->kwidth, x->vwidth, x->hashf, x->equalf, x->data); xh_bucket_realloc(&y, newsize); - xh_begin(&it, x); - while (xh_next(&it)) { - idx = ((unsigned)it.e->hash) % y.size; + for (it = xh_begin(x); it != NULL; it = xh_next(it)) { + idx = ((unsigned)it->hash) % y.size; /* reuse entry object */ - it.e->next = y.buckets[idx]; - y.buckets[idx] = it.e; + it->next = y.buckets[idx]; + y.buckets[idx] = it; y.count++; } + y.chain = x->chain; + free(x->buckets); /* copy all members from y to x */ @@ -169,6 +171,16 @@ xh_put_(xhash *x, const void *key, void *val) memcpy((void *)e->key, key, x->kwidth); memcpy(e->val, val, x->vwidth); + if (x->chain == NULL) { + x->chain = e; + e->fw = e->bw = NULL; + } else { + x->chain->fw = e; + e->bw = x->chain; + e->fw = NULL; + x->chain = e; + } + x->count++; return x->buckets[idx] = e; @@ -179,28 +191,54 @@ xh_del_(xhash *x, const void *key) { int hash; size_t idx; - xh_entry *e, *d; + xh_entry *p, *q, *r; hash = x->hashf(key, x->data); idx = ((unsigned)hash) % x->size; if (x->buckets[idx]->hash == hash && x->equalf(key, x->buckets[idx]->key, x->data)) { - e = x->buckets[idx]->next; - free(x->buckets[idx]); - x->buckets[idx] = e; + q = x->buckets[idx]; + if (q->fw) { + q->fw->bw = q->bw; + } + if (q->bw) { + q->bw->fw = q->fw; + } + if (x->chain == q) { + x->chain = q->bw; + } + r = q->next; + free(q); + x->buckets[idx] = r; } else { - for (e = x->buckets[idx]; ; e = e->next) { - if (e->next->hash == hash && x->equalf(key, e->next->key, x->data)) + for (p = x->buckets[idx]; ; p = p->next) { + if (p->next->hash == hash && x->equalf(key, p->next->key, x->data)) break; } - d = e->next->next; - free(e->next); - e->next = d; + q = p->next; + if (q->fw) { + q->fw->bw = q->bw; + } + if (q->bw) { + q->bw->fw = q->fw; + } + if (x->chain == q) { + x->chain = q->bw; + } + r = q->next; + free(q); + p->next = r; } x->count--; } +static inline size_t +xh_size(xhash *x) +{ + return x->count; +} + static inline void xh_clear(xhash *x) { @@ -217,6 +255,7 @@ xh_clear(xhash *x) x->buckets[i] = NULL; } + x->chain = NULL; x->count = 0; } @@ -361,43 +400,16 @@ xh_del_int(xhash *x, int key) /** iteration */ -static inline void -xh_begin(xh_iter *it, xhash *x) +static inline xh_entry * +xh_begin(xhash *x) { - size_t bidx; - - it->x = x; - - for (bidx = 0; bidx < x->size; ++bidx) { - if (x->buckets[bidx]) - break; - } - it->e = NULL; - it->next = x->buckets[bidx]; - it->bidx = bidx; + return x->chain; } -static inline int -xh_next(xh_iter *it) +static inline xh_entry * +xh_next(xh_entry *e) { - size_t bidx; - - if (! it->next) { - return 0; - } - - it->e = it->next; - if (it->next->next) { - it->next = it->next->next; - return 1; - } - for (bidx = it->bidx + 1; bidx < it->x->size; ++bidx) { - if (it->x->buckets[bidx]) - break; - } - it->next = it->x->buckets[bidx]; - it->bidx = bidx; - return 1; + return e->bw; } #if defined(__cplusplus) diff --git a/lib.c b/lib.c index f9ccacdd..b716d41e 100644 --- a/lib.c +++ b/lib.c @@ -71,7 +71,7 @@ import_table(pic_state *pic, pic_value spec, xhash *imports) xhash table; pic_value val; pic_sym sym, id, tag; - xh_iter it; + xh_entry *it; xh_init_int(&table, sizeof(pic_sym)); @@ -97,11 +97,10 @@ import_table(pic_state *pic, pic_value spec, xhash *imports) } if (tag == pic->sPREFIX) { import_table(pic, pic_cadr(pic, spec), &table); - xh_begin(&it, &table); - while (xh_next(&it)) { + for (it = xh_begin(&table); it != NULL; it = xh_next(it)) { val = pic_list_ref(pic, spec, 2); - sym = pic_intern_str(pic, pic_format(pic, "~s~s", val, pic_sym_value(xh_key(it.e, pic_sym)))); - xh_put_int(imports, sym, &xh_val(it.e, pic_sym)); + sym = pic_intern_str(pic, pic_format(pic, "~s~s", val, pic_sym_value(xh_key(it, pic_sym)))); + xh_put_int(imports, sym, &xh_val(it, pic_sym)); } goto exit; } @@ -117,9 +116,8 @@ import_table(pic_state *pic, pic_value spec, xhash *imports) if (! lib) { pic_errorf(pic, "library not found: ~a", spec); } - xh_begin(&it, &lib->exports); - while (xh_next(&it)) { - xh_put_int(imports, xh_key(it.e, pic_sym), &xh_val(it.e, pic_sym)); + for (it = xh_begin(&lib->exports); it != NULL; it = xh_next(it)) { + xh_put_int(imports, xh_key(it, pic_sym), &xh_val(it, pic_sym)); } exit: @@ -130,20 +128,19 @@ static void import(pic_state *pic, pic_value spec) { xhash imports; - xh_iter it; + xh_entry *it; xh_init_int(&imports, sizeof(pic_sym)); /* pic_sym to pic_sym */ import_table(pic, spec, &imports); - xh_begin(&it, &imports); - while (xh_next(&it)) { + for (it = xh_begin(&imports); it != NULL; it = xh_next(it)) { #if DEBUG - printf("* importing %s as %s\n", pic_symbol_name(pic, xh_key(it.e, pic_sym)), pic_symbol_name(pic, xh_val(it.e, pic_sym))); + printf("* importing %s as %s\n", pic_symbol_name(pic, xh_key(it, pic_sym)), pic_symbol_name(pic, xh_val(it, pic_sym))); #endif - pic_put_rename(pic, pic->lib->env, xh_key(it.e, pic_sym), xh_val(it.e, pic_sym)); + pic_put_rename(pic, pic->lib->env, xh_key(it, pic_sym), xh_val(it, pic_sym)); } xh_destroy(&imports); diff --git a/state.c b/state.c index b93559f4..e7300e9c 100644 --- a/state.c +++ b/state.c @@ -177,7 +177,7 @@ pic_open(int argc, char *argv[], char **envp) void pic_close(pic_state *pic) { - xh_iter it; + xh_entry *it; /* invoke exit handlers */ while (pic->blk) { @@ -221,9 +221,8 @@ pic_close(pic_state *pic) free(pic->arena); /* free symbol names */ - xh_begin(&it, &pic->sym_names); - while (xh_next(&it)) { - free(xh_val(it.e, char *)); + for (it = xh_begin(&pic->sym_names); it != NULL; it = xh_next(it)) { + free(xh_val(it, char *)); } xh_destroy(&pic->sym_names); diff --git a/write.c b/write.c index 685a5108..752964a1 100644 --- a/write.c +++ b/write.c @@ -209,8 +209,7 @@ write_core(struct writer_control *p, pic_value obj) pic_state *pic = p->pic; xFILE *file = p->file; size_t i; - xh_entry *e; - xh_iter it; + xh_entry *e, *it; int c; float f; @@ -334,12 +333,11 @@ write_core(struct writer_control *p, pic_value obj) break; case PIC_TT_DICT: xfprintf(file, "#.(dictionary"); - xh_begin(&it, &pic_dict_ptr(obj)->hash); - while (xh_next(&it)) { + for (it = xh_begin(&pic_dict_ptr(obj)->hash); it != NULL; it = xh_next(it)) { xfprintf(file, " '"); - write_core(p, xh_key(it.e, pic_value)); + write_core(p, xh_key(it, pic_value)); xfprintf(file, " '"); - write_core(p, xh_val(it.e, pic_value)); + write_core(p, xh_val(it, pic_value)); } xfprintf(file, ")"); break;