diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2014-09-30 20:15:27 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2014-09-30 20:15:27 +0900 |
| commit | 4a55b42984d677895d43ddb1bd89c394c3625009 (patch) | |
| tree | 2eb3ee8bdec3b4ce55adf1de430a78cac8cdec4b | |
| parent | 3e3048ddd15ab6e593830f4f63b97b044a529e4a (diff) | |
| download | mruby-4a55b42984d677895d43ddb1bd89c394c3625009.tar.gz mruby-4a55b42984d677895d43ddb1bd89c394c3625009.zip | |
O(1) mrb_sym2name_len(); close #2591
instead of adding sym->name hash table, linear symbol table is added, and reduced name->sym hash table size.
| -rw-r--r-- | include/mruby.h | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-symbol-ext/src/symbol.c | 15 | ||||
| -rw-r--r-- | src/symbol.c | 91 |
3 files changed, 52 insertions, 58 deletions
diff --git a/include/mruby.h b/include/mruby.h index 480080e8b..2fd0a4af7 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -165,7 +165,9 @@ typedef struct mrb_state { struct alloca_header *mems; mrb_sym symidx; - struct kh_n2s *name2sym; /* symbol table */ + struct kh_n2s *name2sym; /* symbol hash */ + struct symbol_name *symtbl; /* symbol table */ + size_t symcapa; #ifdef ENABLE_DEBUG void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); diff --git a/mrbgems/mruby-symbol-ext/src/symbol.c b/mrbgems/mruby-symbol-ext/src/symbol.c index 7ca749999..a96c4017f 100644 --- a/mrbgems/mruby-symbol-ext/src/symbol.c +++ b/mrbgems/mruby-symbol-ext/src/symbol.c @@ -7,8 +7,6 @@ typedef struct symbol_name { const char *name; } symbol_name; -KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE) - /* * call-seq: * Symbol.all_symbols => array @@ -27,16 +25,11 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE) static mrb_value mrb_sym_all_symbols(mrb_state *mrb, mrb_value self) { - khiter_t k; - mrb_sym sym; - khash_t(n2s) *h = mrb->name2sym; - mrb_value ary = mrb_ary_new_capa(mrb, kh_size(h)); + mrb_sym i, lim; + mrb_value ary = mrb_ary_new_capa(mrb, mrb->symidx); - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - sym = kh_value(h, k); - mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); - } + for (i=1, lim=mrb->symidx+1; i<lim; i++) { + mrb_ary_push(mrb, ary, mrb_symbol_value(i)); } return ary; diff --git a/src/symbol.c b/src/symbol.c index e60fa56f5..2a4a0c15a 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -20,21 +20,21 @@ typedef struct symbol_name { } symbol_name; static inline khint_t -sym_hash_func(mrb_state *mrb, const symbol_name s) +sym_hash_func(mrb_state *mrb, mrb_sym s) { khint_t h = 0; - size_t i; - const char *p = s.name; + size_t i, len = mrb->symtbl[s].len;; + const char *p = mrb->symtbl[s].name; - for (i=0; i<s.len; i++) { + for (i=0; i<len; i++) { h = (h << 5) - h + *p++; } return h; } -#define sym_hash_equal(mrb,a, b) (a.len == b.len && memcmp(a.name, b.name, a.len) == 0) +#define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0) -KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE) -KHASH_DEFINE (n2s, symbol_name, mrb_sym, TRUE, sym_hash_func, sym_hash_equal) +KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE) +KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal) /* ------------------------------------------------------ */ static void @@ -49,31 +49,42 @@ static mrb_sym sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) { khash_t(n2s) *h = mrb->name2sym; - symbol_name sname; + symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */ khiter_t k; mrb_sym sym; char *p; sym_validate_len(mrb, len); - sname.lit = lit; - sname.len = (uint16_t)len; - sname.name = name; - k = kh_get(n2s, mrb, h, sname); - if (k != kh_end(h)) - return kh_value(h, k); + if (sname) { + sname->lit = lit; + sname->len = (uint16_t)len; + sname->name = name; + k = kh_get(n2s, mrb, h, 0); + if (k != kh_end(h)) + return kh_key(h, k); + } + /* registering a new symbol */ sym = ++mrb->symidx; + if (mrb->symcapa < sym) { + if (mrb->symcapa == 0) mrb->symcapa = 100; + else mrb->symcapa *= 1.2; + mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1)); + } + sname = &mrb->symtbl[sym]; + sname->len = (uint16_t)len; if (lit) { - sname.name = name; + sname->name = name; + sname->lit = TRUE; } else { p = (char *)mrb_malloc(mrb, len+1); memcpy(p, name, len); p[len] = 0; - sname.name = (const char*)p; + sname->name = (const char*)p; + sname->lit = FALSE; } - k = kh_put(n2s, mrb, h, sname); - kh_value(h, k) = sym; + kh_put(n2s, mrb, h, sym); return sym; } @@ -106,16 +117,16 @@ MRB_API mrb_value mrb_check_intern(mrb_state *mrb, const char *name, size_t len) { khash_t(n2s) *h = mrb->name2sym; - symbol_name sname = { 0 }; + symbol_name *sname = mrb->symtbl; khiter_t k; sym_validate_len(mrb, len); - sname.len = (uint16_t)len; - sname.name = name; + sname->len = (uint16_t)len; + sname->name = name; - k = kh_get(n2s, mrb, h, sname); + k = kh_get(n2s, mrb, h, 0); if (k != kh_end(h)) { - return mrb_symbol_value(kh_value(h, k)); + return mrb_symbol_value(kh_key(h, k)); } return mrb_nil_value(); } @@ -136,37 +147,25 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str) MRB_API const char* mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) { - khash_t(n2s) *h = mrb->name2sym; - khiter_t k; - symbol_name sname; - - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - if (kh_value(h, k) == sym) { - sname = kh_key(h, k); - if (lenp) *lenp = sname.len; - return sname.name; - } - } + if (sym == 0 || mrb->symidx < sym) { + return NULL; } - if (lenp) *lenp = 0; - return NULL; /* missing */ + + if (lenp) *lenp = mrb->symtbl[sym].len; + return mrb->symtbl[sym].name; } void mrb_free_symtbl(mrb_state *mrb) { - khash_t(n2s) *h = mrb->name2sym; - khiter_t k; + mrb_sym i, lim; - for (k = kh_begin(h); k != kh_end(h); k++) - if (kh_exist(h, k)) { - symbol_name s = kh_key(h, k); - - if (!s.lit) { - mrb_free(mrb, (char*)s.name); - } + for (i=1, lim=mrb->symidx+1; i<lim; i++) { + if (!mrb->symtbl[i].lit) { + mrb_free(mrb, (char*)mrb->symtbl[i].name); } + } + mrb_free(mrb, mrb->symtbl); kh_destroy(n2s, mrb, mrb->name2sym); } |
