X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fpcl%2Fcache.lisp;h=f70a2a8f8ac8f6e2350423a90357c0077896964b;hb=8396eebfbac967b5710b55d0a6b842962ed34228;hp=5ce3ac1e4c9a3758b871f933ff149783c210c57d;hpb=a3f37bab2cbaf80db811d480d5b2b95850def3b9;p=sbcl.git diff --git a/src/pcl/cache.lisp b/src/pcl/cache.lisp index 5ce3ac1..f70a2a8 100644 --- a/src/pcl/cache.lisp +++ b/src/pcl/cache.lisp @@ -81,7 +81,8 @@ ;; (mod index (length vector)) ;; using a bitmask. (vector #() :type simple-vector) - ;; The bitmask used to calculate (mod (* line-size line-hash) (length vector))). + ;; The bitmask used to calculate + ;; (mod (* line-size line-hash) (length vector))). (mask 0 :type fixnum) ;; Current probe-depth needed in the cache. (depth 0 :type index) @@ -148,22 +149,6 @@ (defun cache-key-p (thing) (not (symbolp thing))) -(eval-when (:compile-toplevel :load-toplevel :execute) - (sb-kernel:define-structure-slot-compare-and-swap compare-and-swap-cache-depth - :structure cache - :slot depth)) - -;;; Utility macro for atomic updates without locking... doesn't -;;; do much right now, and it would be nice to make this more magical. -(defmacro compare-and-swap (place old new) - (unless (consp place) - (error "Don't know how to compare and swap ~S." place)) - (ecase (car place) - (svref - `(simple-vector-compare-and-swap ,@(cdr place) ,old ,new)) - (cache-depth - `(compare-and-swap-cache-depth ,@(cdr place) ,old ,new)))) - ;;; Atomically update the current probe depth of a cache. (defun note-cache-depth (cache depth) (loop for old = (cache-depth cache) @@ -336,17 +321,25 @@ ;;;; Copies and expands the cache, dropping any invalidated or ;;;; incomplete lines. -(defun copy-and-expand-cache (cache) +(defun copy-and-expand-cache (cache layouts value) (let ((copy (%copy-cache cache)) (length (length (cache-vector cache)))) (when (< length +cache-vector-max-length+) (setf length (* 2 length))) (tagbody :again - (setf (cache-vector copy) (make-array length :initial-element '..empty..) + ;; Blow way the old vector first, so a GC potentially triggered by + ;; MAKE-ARRAY can collect it. + (setf (cache-vector copy) #() + (cache-vector copy) (make-array length :initial-element '..empty..) (cache-depth copy) 0 (cache-mask copy) (compute-cache-mask length (cache-line-size cache)) (cache-limit copy) (compute-limit (/ length (cache-line-size cache)))) + ;; First insert the new one -- if we don't do this first and + ;; the cache has reached it's maximum size we may end up + ;; looping in FILL-CACHE. + (unless (try-update-cache copy layouts value) + (bug "Could not insert ~S:~S to supposedly empty ~S." layouts value cache)) (map-cache (lambda (layouts value) (unless (try-update-cache copy layouts value) ;; If the cache would grow too much we drop the @@ -409,7 +402,7 @@ ;; we just drop the invalid entries. (%fill-cache (copy-cache cache) layouts value)) (t - (%fill-cache (copy-and-expand-cache cache) layouts value))))) + (copy-and-expand-cache cache layouts value))))) (if (listp layouts) (%fill-cache cache layouts value) (%fill-cache cache (list layouts) value))))