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.
parent 3e3048dd
...@@ -165,7 +165,9 @@ typedef struct mrb_state { ...@@ -165,7 +165,9 @@ typedef struct mrb_state {
struct alloca_header *mems; struct alloca_header *mems;
mrb_sym symidx; 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 #ifdef ENABLE_DEBUG
void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
......
...@@ -7,8 +7,6 @@ typedef struct symbol_name { ...@@ -7,8 +7,6 @@ typedef struct symbol_name {
const char *name; const char *name;
} symbol_name; } symbol_name;
KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE)
/* /*
* call-seq: * call-seq:
* Symbol.all_symbols => array * Symbol.all_symbols => array
...@@ -27,16 +25,11 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE) ...@@ -27,16 +25,11 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, TRUE)
static mrb_value static mrb_value
mrb_sym_all_symbols(mrb_state *mrb, mrb_value self) mrb_sym_all_symbols(mrb_state *mrb, mrb_value self)
{ {
khiter_t k; mrb_sym i, lim;
mrb_sym sym; mrb_value ary = mrb_ary_new_capa(mrb, mrb->symidx);
khash_t(n2s) *h = mrb->name2sym;
mrb_value ary = mrb_ary_new_capa(mrb, kh_size(h));
for (k = kh_begin(h); k != kh_end(h); k++) { for (i=1, lim=mrb->symidx+1; i<lim; i++) {
if (kh_exist(h, k)) { mrb_ary_push(mrb, ary, mrb_symbol_value(i));
sym = kh_value(h, k);
mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
}
} }
return ary; return ary;
......
...@@ -20,21 +20,21 @@ typedef struct symbol_name { ...@@ -20,21 +20,21 @@ typedef struct symbol_name {
} symbol_name; } symbol_name;
static inline khint_t 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; khint_t h = 0;
size_t i; size_t i, len = mrb->symtbl[s].len;;
const char *p = s.name; 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++; h = (h << 5) - h + *p++;
} }
return h; 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_DECLARE(n2s, mrb_sym, mrb_sym, FALSE)
KHASH_DEFINE (n2s, symbol_name, mrb_sym, TRUE, sym_hash_func, sym_hash_equal) KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal)
/* ------------------------------------------------------ */ /* ------------------------------------------------------ */
static void static void
...@@ -49,31 +49,42 @@ static mrb_sym ...@@ -49,31 +49,42 @@ static mrb_sym
sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
{ {
khash_t(n2s) *h = mrb->name2sym; khash_t(n2s) *h = mrb->name2sym;
symbol_name sname; symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
khiter_t k; khiter_t k;
mrb_sym sym; mrb_sym sym;
char *p; char *p;
sym_validate_len(mrb, len); sym_validate_len(mrb, len);
sname.lit = lit; if (sname) {
sname.len = (uint16_t)len; sname->lit = lit;
sname.name = name; sname->len = (uint16_t)len;
k = kh_get(n2s, mrb, h, sname); sname->name = name;
if (k != kh_end(h)) k = kh_get(n2s, mrb, h, 0);
return kh_value(h, k); if (k != kh_end(h))
return kh_key(h, k);
}
/* registering a new symbol */
sym = ++mrb->symidx; 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) { if (lit) {
sname.name = name; sname->name = name;
sname->lit = TRUE;
} }
else { else {
p = (char *)mrb_malloc(mrb, len+1); p = (char *)mrb_malloc(mrb, len+1);
memcpy(p, name, len); memcpy(p, name, len);
p[len] = 0; p[len] = 0;
sname.name = (const char*)p; sname->name = (const char*)p;
sname->lit = FALSE;
} }
k = kh_put(n2s, mrb, h, sname); kh_put(n2s, mrb, h, sym);
kh_value(h, k) = sym;
return sym; return sym;
} }
...@@ -106,16 +117,16 @@ MRB_API mrb_value ...@@ -106,16 +117,16 @@ MRB_API mrb_value
mrb_check_intern(mrb_state *mrb, const char *name, size_t len) mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
{ {
khash_t(n2s) *h = mrb->name2sym; khash_t(n2s) *h = mrb->name2sym;
symbol_name sname = { 0 }; symbol_name *sname = mrb->symtbl;
khiter_t k; khiter_t k;
sym_validate_len(mrb, len); sym_validate_len(mrb, len);
sname.len = (uint16_t)len; sname->len = (uint16_t)len;
sname.name = name; sname->name = name;
k = kh_get(n2s, mrb, h, sname); k = kh_get(n2s, mrb, h, 0);
if (k != kh_end(h)) { 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(); return mrb_nil_value();
} }
...@@ -136,37 +147,25 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str) ...@@ -136,37 +147,25 @@ mrb_check_intern_str(mrb_state *mrb, mrb_value str)
MRB_API const char* MRB_API const char*
mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
{ {
khash_t(n2s) *h = mrb->name2sym; if (sym == 0 || mrb->symidx < sym) {
khiter_t k; return NULL;
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 (lenp) *lenp = 0;
return NULL; /* missing */ if (lenp) *lenp = mrb->symtbl[sym].len;
return mrb->symtbl[sym].name;
} }
void void
mrb_free_symtbl(mrb_state *mrb) mrb_free_symtbl(mrb_state *mrb)
{ {
khash_t(n2s) *h = mrb->name2sym; mrb_sym i, lim;
khiter_t k;
for (k = kh_begin(h); k != kh_end(h); k++) for (i=1, lim=mrb->symidx+1; i<lim; i++) {
if (kh_exist(h, k)) { if (!mrb->symtbl[i].lit) {
symbol_name s = kh_key(h, k); mrb_free(mrb, (char*)mrb->symtbl[i].name);
if (!s.lit) {
mrb_free(mrb, (char*)s.name);
}
} }
}
mrb_free(mrb, mrb->symtbl);
kh_destroy(n2s, mrb, mrb->name2sym); kh_destroy(n2s, mrb, mrb->name2sym);
} }
......
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