fixing bug in hash table. growth schedule made it possible for

maxprobe to decrease, causing growth during rehashing, which leaks
the table.
This commit is contained in:
JeffBezanson 2009-03-28 23:46:02 +00:00
parent e3158b8640
commit 2ddbac400a
2 changed files with 58 additions and 37 deletions

View File

@ -8,7 +8,7 @@
(define Instructions (define Instructions
(make-enum-table (make-enum-table
[:nop :dup :pop :popn :call :jmp :brf :brt :jmp.s :brf.s :brt.s :ret [:nop :dup :pop :popn :call :jmp :brf :brt :jmp.l :brf.l :brt.l :ret
:eq? :eqv? :equal? :atom? :not :null? :boolean? :symbol? :eq? :eqv? :equal? :atom? :not :null? :boolean? :symbol?
:number? :bound? :pair? :builtin? :vector? :fixnum? :number? :bound? :pair? :builtin? :vector? :fixnum?
@ -20,9 +20,9 @@
:vector :aref :aset :length :for :vector :aref :aset :length :for
:loadt :loadf :loadnil :load0 :load1 :loadv :loadv.s :loadt :loadf :loadnil :load0 :load1 :loadv :loadv.l
:loadg :loada :loadc :loadg :loada :loadc
:setg :seta :setc :loadg.s :setg.s :setg :seta :setc :loadg.l :setg.l
:closure :trycatch])) :closure :trycatch]))
@ -41,21 +41,38 @@
(- nconst 1))))) (- nconst 1)))))
(aset! e 2 nconst) (aset! e 2 nconst)
(set! args (list vind)) (set! args (list vind))
(if (< vind 256) (if (>= vind 256)
(set! inst (case inst (set! inst (case inst
(:loadv :loadv.s) (:loadv :loadv.l)
(:loadg :loadg.s) (:loadg :loadg.l)
(:setg :setg.s)))))) (:setg :setg.l))))))
(aset! e 0 (nreconc (cons inst args) (aref e 0))) (aset! e 0 (nreconc (cons inst args) (aref e 0)))
e) e)
(define (make-label e) (gensym)) (define (make-label e) (gensym))
(define (mark-label e l) (emit e :label l)) (define (mark-label e l) (emit e :label l))
(define (count- f l n)
(if (null? l)
n
(count- f (cdr l) (if (f (car l))
(+ n 1)
n))))
(define (count f l) (count- f l 0))
(define (peephole c) c)
; convert symbolic bytecode representation to a byte array. ; convert symbolic bytecode representation to a byte array.
; labels are fixed-up. ; labels are fixed-up.
(define (encode-byte-code e) (define (encode-byte-code e)
(let ((v (list->vector (nreverse e)))) (let* ((cl (peephole (nreverse e)))
(long? (>= (+ (length cl)
(* 3 (count (lambda (i)
(memq i '(:loadv :loadg :setg
:jmp :brt :brf)))
cl)))
65536))
(v (list->vector cl)))
(let ((n (length v)) (let ((n (length v))
(i 0) (i 0)
(label-to-loc (table)) (label-to-loc (table))
@ -69,16 +86,25 @@
(begin (put! label-to-loc (aref v (+ i 1)) (sizeof bcode)) (begin (put! label-to-loc (aref v (+ i 1)) (sizeof bcode))
(set! i (+ i 2))) (set! i (+ i 2)))
(begin (begin
(io.write bcode (byte (get Instructions vi))) (io.write bcode
(byte
(get Instructions
(if (and long?
(memq vi '(:jmp :brt :brf)))
(case vi
(:jmp :jmp.l)
(:brt :brt.l)
(:brf :brf.l))
vi))))
(set! i (+ i 1)) (set! i (+ i 1))
(if (< i n) (if (< i n)
(let ((nxt (aref v i))) (let ((nxt (aref v i)))
(case vi (case vi
((:loadv :loadg :setg) ((:loadv.l :loadg.l :setg.l)
(io.write bcode (uint32 nxt)) (io.write bcode (uint32 nxt))
(set! i (+ i 1))) (set! i (+ i 1)))
((:loada :seta :call :loadv.s :loadg.s :setg.s :popn) ((:loada :seta :call :loadv :loadg :setg :popn)
(io.write bcode (uint8 nxt)) (io.write bcode (uint8 nxt))
(set! i (+ i 1))) (set! i (+ i 1)))
@ -89,27 +115,16 @@
(set! i (+ i 1))) (set! i (+ i 1)))
((:jmp :brf :brt) ((:jmp :brf :brt)
(let ((dest (get label-to-loc nxt #uint32(-1))))
(if (< dest 256)
(begin (io.seek bcode (1- (sizeof bcode)))
(io.write bcode
(byte
(get Instructions
(case vi
(:jmp :jmp.s)
(:brt :brt.s)
(:brf :brf.s)))))
(io.write bcode (uint8 dest)))
(begin
(put! fixup-to-label (sizeof bcode) nxt) (put! fixup-to-label (sizeof bcode) nxt)
(io.write bcode (uint32 0))))) (io.write bcode ((if long? uint32 uint16) 0))
(set! i (+ i 1))) (set! i (+ i 1)))
(else #f)))))))) (else #f))))))))
(table.foreach (table.foreach
(lambda (addr labl) (lambda (addr labl)
(begin (io.seek bcode addr) (begin (io.seek bcode addr)
(io.write bcode (uint32 (get label-to-loc labl))))) (io.write bcode ((if long? uint32 uint16)
(get label-to-loc labl)))))
fixup-to-label) fixup-to-label)
(io.tostring! bcode)))) (io.tostring! bcode))))
@ -169,9 +184,11 @@
(if (atom? lst) (if (atom? lst)
lst lst
(let ((clause (car lst))) (let ((clause (car lst)))
(if (eq? (car clause) 'else)
(cons 'begin (cdr clause))
`(if ,(car clause) `(if ,(car clause)
,(cons 'begin (cdr clause)) ,(cons 'begin (cdr clause))
,(cond-clauses->if (cdr lst)))))) ,(cond-clauses->if (cdr lst)))))))
(define (compile-if g x env) (define (compile-if g x env)
(let ((elsel (make-label g)) (let ((elsel (make-label g))
@ -306,6 +323,10 @@
(ash (aref a (+ i 2)) 16) (ash (aref a (+ i 2)) 16)
(ash (aref a (+ i 3)) 24))) (ash (aref a (+ i 3)) 24)))
(define (ref-uint16-LE a i)
(+ (ash (aref a (+ i 0)) 0)
(ash (aref a (+ i 1)) 8)))
(define (hex5 n) (define (hex5 n)
(pad-l (number->string n 16) 5 #\0)) (pad-l (number->string n 16) 5 #\0))
@ -330,11 +351,11 @@
(string.tail (string inst) 1) "\t") (string.tail (string inst) 1) "\t")
(set! i (+ i 1)) (set! i (+ i 1))
(case inst (case inst
((:loadv :loadg :setg) ((:loadv.l :loadg.l :setg.l)
(print-val (aref vals (ref-uint32-LE code i))) (print-val (aref vals (ref-uint32-LE code i)))
(set! i (+ i 4))) (set! i (+ i 4)))
((:loadv.s :loadg.s :setg.s) ((:loadv :loadg :setg)
(print-val (aref vals (aref code i))) (print-val (aref vals (aref code i)))
(set! i (+ i 1))) (set! i (+ i 1)))
@ -349,13 +370,13 @@
(set! i (+ i 1))) (set! i (+ i 1)))
((:jmp :brf :brt) ((:jmp :brf :brt)
(princ "@" (hex5 (ref-uint16-LE code i)))
(set! i (+ i 2)))
((:jmp.l :brf.l :brt.l)
(princ "@" (hex5 (ref-uint32-LE code i))) (princ "@" (hex5 (ref-uint32-LE code i)))
(set! i (+ i 4))) (set! i (+ i 4)))
((:jmp.s :brf.s :brt.s)
(princ "@" (hex5 (aref code i)))
(set! i (+ i 1)))
(else #f)))))))) (else #f))))))))
(define (disassemble b) (disassemble- b 0)) (define (disassemble b) (disassemble- b 0))

View File

@ -7,7 +7,7 @@
#define hash_size(h) ((h)->size/2) #define hash_size(h) ((h)->size/2)
// compute empirical max-probe for a given size // compute empirical max-probe for a given size
#define max_probe(size) ((size)<=HT_N_INLINE/2 ? HT_N_INLINE/2 : (size)>>5) #define max_probe(size) ((size)<=(HT_N_INLINE*2) ? (HT_N_INLINE/2) : (size)>>3)
#define HTIMPL(HTNAME, HFUNC, EQFUNC) \ #define HTIMPL(HTNAME, HFUNC, EQFUNC) \
static void **HTNAME##_lookup_bp(htable_t *h, void *key) \ static void **HTNAME##_lookup_bp(htable_t *h, void *key) \
@ -47,7 +47,7 @@ static void **HTNAME##_lookup_bp(htable_t *h, void *key) \
/* lots of time rehashing all the keys over and over. */ \ /* lots of time rehashing all the keys over and over. */ \
sz = h->size; \ sz = h->size; \
ol = h->table; \ ol = h->table; \
if (sz >= (1<<19)) \ if (sz >= (1<<19) || (sz <= (1<<8))) \
newsz = sz<<1; \ newsz = sz<<1; \
else if (sz <= HT_N_INLINE) \ else if (sz <= HT_N_INLINE) \
newsz = 32; \ newsz = 32; \