switching to chained buckets for symbol table

This commit is contained in:
Alex Shinn 2009-04-03 02:02:59 +09:00
parent 9a816f504f
commit 2983b10af1
6 changed files with 41 additions and 43 deletions

View file

@ -10,7 +10,7 @@ INCDIR=$(PREFIX)/include/chibi-scheme
MODDIR=$(PREFIX)/share/chibi-scheme MODDIR=$(PREFIX)/share/chibi-scheme
SO=.dylib SO=.dylib
CFLAGS=-Wall -g -fno-inline -save-temps -Os CFLAGS=-Wall -g -save-temps -Os
GC_OBJ=./gc/gc.a GC_OBJ=./gc/gc.a

View file

@ -31,6 +31,10 @@
#define USE_HUFF_SYMS 1 #define USE_HUFF_SYMS 1
#endif #endif
#ifndef USE_HASH_SYMS
#define USE_HASH_SYMS 1
#endif
#ifndef USE_DEBUG #ifndef USE_DEBUG
#define USE_DEBUG 1 #define USE_DEBUG 1
#endif #endif

View file

@ -1,7 +1,4 @@
;; syntax-rules
;; symbol->string string->symbol
;; provide c[ad]{2,4}r ;; provide c[ad]{2,4}r
(define (caar x) (car (car x))) (define (caar x) (car (car x)))
@ -314,6 +311,9 @@
;; string utils ;; string utils
(define (symbol->string sym)
(call-with-output-string (lambda (out) (write sym out))))
(define (list->string ls) (define (list->string ls)
(let ((str (make-string (length ls) #\space))) (let ((str (make-string (length ls) #\space)))
(let lp ((ls ls) (i 0)) (let lp ((ls ls) (i 0))

View file

@ -85,6 +85,7 @@ _FN2OPT(SEXP_FIXNUM, SEXP_CHAR, "make-string", sexp_make_character(' '), sexp_ma
_FN2(SEXP_STRING, SEXP_STRING, "string-cmp", 0, sexp_string_cmp), _FN2(SEXP_STRING, SEXP_STRING, "string-cmp", 0, sexp_string_cmp),
_FN2(SEXP_STRING, SEXP_STRING, "string-cmp-ci", 0, sexp_string_cmp_ci), _FN2(SEXP_STRING, SEXP_STRING, "string-cmp-ci", 0, sexp_string_cmp_ci),
_FN3(SEXP_STRING, SEXP_FIXNUM, "substring", 0, sexp_substring), _FN3(SEXP_STRING, SEXP_FIXNUM, "substring", 0, sexp_substring),
_FN1(SEXP_STRING, "string->symbol", 0, sexp_string_to_symbol),
_FN1(SEXP_PAIR, "string-concatenate", 0, sexp_string_concatenate), _FN1(SEXP_PAIR, "string-concatenate", 0, sexp_string_concatenate),
_FN2(0, SEXP_PAIR, "memq", 0, sexp_memq), _FN2(0, SEXP_PAIR, "memq", 0, sexp_memq),
_FN2(0, SEXP_PAIR, "assq", 0, sexp_assq), _FN2(0, SEXP_PAIR, "assq", 0, sexp_assq),

68
sexp.c
View file

@ -45,13 +45,13 @@ static int is_separator(int c) {
return 0<c && c<0x60 && sexp_separators[c]; return 0<c && c<0x60 && sexp_separators[c];
} }
static sexp* symbol_table = NULL; #if USE_HASH_SYMS
static unsigned long symbol_table_primes[] = { #define SEXP_SYMBOL_TABLE_SIZE 389
/* 97, 389, */ 1543, 6151, 12289, 24593, 49157, 98317, 196613, 393241, #else
786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, #define SEXP_SYMBOL_TABLE_SIZE 1
100663319, 201326611, 402653189, 805306457, 1610612741}; #endif
static int symbol_table_prime_index = 0;
static int symbol_table_count = 0; static sexp symbol_table[SEXP_SYMBOL_TABLE_SIZE];
sexp sexp_alloc_tagged(size_t size, sexp_uint_t tag) { sexp sexp_alloc_tagged(size_t size, sexp_uint_t tag) {
sexp res = (sexp) sexp_alloc(size); sexp res = (sexp) sexp_alloc(size);
@ -328,16 +328,16 @@ sexp sexp_substring (sexp str, sexp start, sexp end) {
#define FNV_PRIME 16777619 #define FNV_PRIME 16777619
#define FNV_OFFSET_BASIS 2166136261uL #define FNV_OFFSET_BASIS 2166136261uL
int sexp_string_hash(char *str, int acc) { sexp_uint_t sexp_string_hash(char *str, sexp_uint_t acc) {
while (*str) {acc *= FNV_PRIME; acc ^= *str++;} while (*str) {acc *= FNV_PRIME; acc ^= *str++;}
return acc; return acc;
} }
sexp sexp_intern(char *str) { sexp sexp_intern(char *str) {
struct huff_entry he; struct huff_entry he;
sexp_uint_t len, res=FNV_OFFSET_BASIS, space=3, newbits, i, d, cell; sexp_uint_t len, res=FNV_OFFSET_BASIS, space=3, newbits, bucket;
char c, *mystr, *p=str; char c, *mystr, *p=str;
sexp sym, *newtable; sexp sym, ls;
#if USE_HUFF_SYMS #if USE_HUFF_SYMS
res = 0; res = 0;
@ -354,39 +354,29 @@ sexp sexp_intern(char *str) {
#endif #endif
normal_intern: normal_intern:
res = sexp_string_hash(p, res); #if USE_HASH_SYMS
d = symbol_table_primes[symbol_table_prime_index]; bucket = (sexp_string_hash(p, res) % SEXP_SYMBOL_TABLE_SIZE);
cell = res % d; #else
for (i=0; i<d; i++) { bucket = 0;
if (! symbol_table[cell]) { #endif
break;
} else if (strncmp(str,
sexp_symbol_data(symbol_table[cell]),
sexp_symbol_length(symbol_table[cell])) == 0) {
return symbol_table[cell];
}
cell = (cell * res + 1) % d;
}
symbol_table_count++;
if (symbol_table_count*5 > d*4) {
fprintf(stderr, "resizing symbol table!!!!!\n");
newtable = sexp_alloc(symbol_table_primes[symbol_table_prime_index++]
* sizeof(sexp));
/* XXXX rehash */
sexp_free(symbol_table);
symbol_table = newtable;
}
sym = sexp_alloc_type(symbol, SEXP_SYMBOL);
len = strlen(str); len = strlen(str);
for (ls=symbol_table[bucket]; sexp_pairp(ls); ls=sexp_cdr(ls))
if (strncmp(str, sexp_symbol_data(sexp_car(ls)), len) == 0)
return sexp_car(ls);
/* not found, make a new symbol */
sym = sexp_alloc_type(symbol, SEXP_SYMBOL);
mystr = sexp_alloc(len+1); mystr = sexp_alloc(len+1);
memcpy(mystr, str, len+1); memcpy(mystr, str, len+1);
mystr[len]=0; mystr[len]=0;
sexp_symbol_length(sym) = len; sexp_symbol_length(sym) = len;
sexp_symbol_data(sym) = mystr; sexp_symbol_data(sym) = mystr;
symbol_table[cell] = sym; sexp_push(symbol_table[bucket], sym);
return symbol_table[cell]; return sym;
}
sexp sexp_string_to_symbol (sexp str) {
return sexp_intern(sexp_string_data(str));
} }
sexp sexp_make_vector(sexp len, sexp dflt) { sexp sexp_make_vector(sexp len, sexp dflt) {
@ -1035,6 +1025,7 @@ sexp sexp_read_from_string(char *str) {
} }
void sexp_init() { void sexp_init() {
int i;
if (! sexp_initialized_p) { if (! sexp_initialized_p) {
sexp_initialized_p = 1; sexp_initialized_p = 1;
#if USE_BOEHM #if USE_BOEHM
@ -1042,7 +1033,8 @@ void sexp_init() {
GC_add_roots((char*)&symbol_table, GC_add_roots((char*)&symbol_table,
((char*)&symbol_table)+sizeof(symbol_table)+1); ((char*)&symbol_table)+sizeof(symbol_table)+1);
#endif #endif
symbol_table = sexp_alloc(symbol_table_primes[0]*sizeof(sexp)); for (i=0; i<SEXP_SYMBOL_TABLE_SIZE; i++)
symbol_table[i] = SEXP_NULL;
the_dot_symbol = sexp_intern("."); the_dot_symbol = sexp_intern(".");
the_quote_symbol = sexp_intern("quote"); the_quote_symbol = sexp_intern("quote");
the_quasiquote_symbol = sexp_intern("quasiquote"); the_quasiquote_symbol = sexp_intern("quasiquote");

3
sexp.h
View file

@ -406,8 +406,9 @@ sexp sexp_c_string(char *str);
sexp sexp_make_string(sexp len, sexp ch); sexp sexp_make_string(sexp len, sexp ch);
sexp sexp_substring (sexp str, sexp start, sexp end); sexp sexp_substring (sexp str, sexp start, sexp end);
sexp sexp_make_flonum(double f); sexp sexp_make_flonum(double f);
int sexp_string_hash(char *str, int acc); sexp_uint_t sexp_string_hash(char *str, sexp_uint_t acc);
sexp sexp_intern(char *str); sexp sexp_intern(char *str);
sexp sexp_string_to_symbol(sexp str);
sexp sexp_make_vector(sexp len, sexp dflt); sexp sexp_make_vector(sexp len, sexp dflt);
sexp sexp_list_to_vector(sexp ls); sexp sexp_list_to_vector(sexp ls);
sexp sexp_vector(int count, ...); sexp sexp_vector(int count, ...);