other
(in-package "ACL2")
other
(eval-when (:execute :compile-toplevel :load-toplevel) (when (ignore-errors (mv-let (x y) (funcall (intern "READ-CYCLE-COUNTER" "SB-IMPL")) (not (and (eql x 0) (eql y 0))))) (format t "; Note: pushing :RDTSC onto *features*.~&") (finish-output) (pushnew :rdtsc *features*)))
other
(defg *enable-multithreaded-memoization* nil)
mf-multiprocessingfunction
(defun mf-multiprocessing (flg &optional quiet) (cond ((iff *enable-multithreaded-memoization* flg) (when (not quiet) (format *standard-output* "~%; Note: Multiprocessing is already ~a.~%" (if *enable-multithreaded-memoization* "on" "off")))) (t (unwind-protect (setq *enable-multithreaded-memoization* flg) (rememoize-all t)))) flg)
other
(defg *global-memoize-lock*
(make-lock "*GLOBAL-MEMOIZE-LOCK*"))
with-global-memoize-lockmacro
(defmacro with-global-memoize-lock (&rest forms) `(if *enable-multithreaded-memoization* (with-lock-raw *global-memoize-lock* ,@FORMS) (progn ,@FORMS)))
with-global-memoize-lock-staticmacro
(defmacro with-global-memoize-lock-static (&rest forms) (if *enable-multithreaded-memoization* `(with-lock-raw *global-memoize-lock* . ,FORMS) `(progn . ,FORMS)))
mf-mhtmacro
(defmacro mf-mht (&rest args) (if (assoc-keyword :shared args) `(hl-mht ,@ARGS) `(if *enable-multithreaded-memoization* (hl-mht :shared :default ,@ARGS) (hl-mht ,@ARGS))))
mf-gethashmacro
(defmacro mf-gethash (key ht) `(gethash ,KEY (the hash-table ,HT)))
mf-sethashmacro
(defmacro mf-sethash (key val ht) `(setf (gethash ,KEY (the hash-table ,HT)) ,VAL))
mf-flex-aconsmacro
(defmacro mf-flex-acons (elem al) `(hl-flex-acons ,ELEM ,AL *enable-multithreaded-memoization*))
mf-hash-table-countmacro
(defmacro mf-hash-table-count (ht) `(hash-table-count (the hash-table ,HT)))
mf-hash-table-sizemacro
(defmacro mf-hash-table-size (ht) `(hash-table-size (the hash-table ,HT)))
mf-maphashmacro
(defmacro mf-maphash (lam ht) `(maphash ,LAM (the hash-table ,HT)))
other
(defparameter *record-bytes* (and (or (member :ccl *features*) (member :sbcl *features*) (member :lispworks *features*)) (> most-positive-fixnum (expt 2 32))))
other
(defparameter *record-calls* t)
other
(defparameter *record-hits* t)
other
(defparameter *record-mht-calls* t)
other
(defparameter *record-pons-calls* t)
other
(defparameter *record-time* t)
other
(defg *mf-print-right-margin* 79)
other
(defv *report-bytes* t)
other
(defv *report-calls* t)
other
(defv *report-calls-from* t)
other
(defv *report-calls-to* t)
other
(defv *report-hits* t)
other
(defv *report-mht-calls* t)
other
(defv *report-pons-calls* t)
other
(defv *report-time* t)
other
(defv *report-on-memo-tables* t)
other
(defv *report-on-pons-tables* t)
other
(defg *sort-to-from-by-calls* nil)
other
(defg *memoize-summary-order-reversed* nil)
other
(defg *mf-print-alist-width* 45)
other
(defg *memoize-summary-order-list* '(total-time number-of-calls))
other
(defg *memoize-summary-limit* 100)
other
(defg *condition-nil-as-hit* nil)
other
(defvar *never-memoize-ht* (let ((ht (mf-mht :test 'eq :shared :default))) (loop for x in *stobjs-out-invalid* do (mf-sethash x t ht)) ht))
other
(defg *float-ticks/second* (float (expt 2 31)))
other
(defg *float-ticks/second-initialized* nil)
other
(declaim (float *float-ticks/second*))
other
(defg *pons-call-counter* 0)
other
(defg *pons-misses-counter* 0)
other
(declaim (type mfixnum *pons-call-counter*))
other
(declaim (type mfixnum *pons-misses-counter*))
initial-memoize-info-htfunction
(defun initial-memoize-info-ht nil (if *enable-multithreaded-memoization* (mf-mht :shared :default) (mf-mht)))
other
(defg *memoize-info-ht* (initial-memoize-info-ht))
other
(declaim (hash-table *memoize-info-ht*))
other
(defparameter *memo-max-sizes* (mf-mht :shared :default))
initial-memoize-call-arrayfunction
(defun initial-memoize-call-array (n) (make-array n :element-type 'mfixnum :initial-element 0))
other
(defg *memoize-call-array* (initial-memoize-call-array 1))
other
(declaim (type (simple-array mfixnum (*)) *memoize-call-array*))
other
(defg *callers-array* (make-array 0))
other
(defconstant *ma-bytes-index* 0)
other
(defconstant *ma-hits-index* 1)
other
(defconstant *ma-mht-index* 2)
other
(defconstant *ma-pons-index* 4)
other
(declaim (type (and mfixnum fixnum) *max-symbol-to-fixnum* *initial-2max-memoize-fns* *2max-memoize-fns*))
other
(defconstant *initial-max-symbol-to-fixnum* 4)
other
(defg *max-symbol-to-fixnum* *initial-max-symbol-to-fixnum*)
other
(defv *initial-2max-memoize-fns* 1000)
other
(defg *2max-memoize-fns* *initial-2max-memoize-fns*)
other
(defg *memoize-init-done* nil)
other
(defg *hons-gentemp-counter* 0)
other
(defg *memoize-use-attachment-warning-p* t)
other
(defv *number-of-arguments-and-values-ht* (mf-mht :shared :default))
other
(declaim (hash-table *number-of-arguments-and-values-ht*))
our-syntaxmacro
(defmacro our-syntax (&rest args) `(our-with-standard-io-syntax (let ((*package* (find-package-fast (f-get-global 'current-package *the-live-state*))) (*readtable* *acl2-readtable*)) ,@ARGS)))
our-syntax-nicemacro
(defmacro our-syntax-nice (&rest args) `(our-syntax (setq *print-case* :downcase) (setq *print-pretty* t) (setq *print-readably* nil) (setq *print-right-margin* ,*MF-PRINT-RIGHT-MARGIN*) (setq *print-miser-width* 100) ,@ARGS))
mf-note-arityfunction
(defun mf-note-arity (fn nargs nvals) (mf-sethash fn (cons nargs nvals) *number-of-arguments-and-values-ht*))
memoize-look-up-def-rawfunction
(defun memoize-look-up-def-raw (sym quiet-p) (let ((temp (get sym 'acl2-saved-def))) (cond (temp (cdr temp)) (t (let* ((fn (symbol-function sym)) (lam (and fn (function-lambda-expression fn)))) (cond (lam (assert (or (eq (car lam) 'lambda) (eq (car lam) 'named-lambda))) lam) (quiet-p nil) (t (error "Lisp cannot find a definition for ~ ~s.~%Consider using ~s or supplying to ~ ~%memoize(-fn) an explicit :CL-DEFUN ~ argument.~a" sym 'save-def ""))))))))
other
(defun-one-output mf-len-inputs (fn) (assert (symbolp fn)) (assert (fboundp fn)) (assert (not (macro-function fn))) (assert (not (special-operator-p fn))) (or (let ((pair (mf-gethash fn *number-of-arguments-and-values-ht*))) (and (consp pair) (integerp (car pair)) (car pair))) (let ((formals (getpropc fn 'formals t (w *the-live-state*)))) (and (not (eq t formals)) (length formals))) (let ((def (memoize-look-up-def-raw fn t))) (and def (length (cadr def))))))
other
(defun-one-output mf-len-outputs (fn) (assert (symbolp fn)) (assert (fboundp fn)) (assert (not (macro-function fn))) (assert (not (special-operator-p fn))) (or (let ((pair (mf-gethash fn *number-of-arguments-and-values-ht*))) (and (consp pair) (integerp (cdr pair)) (cdr pair))) (let* ((state *the-live-state*) (w (w state))) (and (not (eq t (getpropc fn 'formals t w))) (len (stobjs-out fn w)))) (and (get fn 'acl2-saved-def) 1)))
other
(defconstant *10-days-in-seconds* (* 10 24 60 60))
10-daysfunction
(defun 10-days nil (let ((n (* *10-days-in-seconds* (ceiling *float-ticks/second*)))) n))
other
(defg *10-days* (10-days))
other
(declaim (type mfixnum *10-days*))
other
(defg *float-internal-time-units-per-second* (float internal-time-units-per-second))
other
(declaim (float *float-internal-time-units-per-second*))
internal-real-ticksmacro
(defmacro internal-real-ticks nil '(the-mfixnum (logand (the-mfixnum (get-internal-real-time)) most-positive-mfixnum)))
other
(defun-one-output float-ticks/second-init
nil
(unless *float-ticks/second-initialized*
(setq *float-ticks/second*
*float-internal-time-units-per-second*)
(setq *10-days* (10-days))
(setq *float-ticks/second-initialized* t)
(check-type *float-ticks/second*
(and float (satisfies plusp)))))
safe-incf-aux-errormacro
(defmacro safe-incf-aux-error (x inc where) `(cond (',WHERE (error "~%; SAFE-INCF-AUX: ** Error: ~a." (list :x ,X :inc ,INC :where ',WHERE))) (t (progn (setf (the mfixnum ,X) most-positive-mfixnum) nil))))
safe-incf-auxmacro
(defmacro safe-incf-aux (x inc &optional where) (cond ((not (or (symbolp inc) (and (< inc most-positive-mfixnum) (> inc 0)))) (safe-incf-aux-error x inc where)) ((and (true-listp x) (equal (len x) 3) (member (car x) '(aref svref)) (symbolp (nth 1 x)) (consp (nth 2 x))) (let ((idx (make-symbol "IDX"))) `(let ((,IDX (the-mfixnum ,(NTH 2 X)))) (declare (type mfixnum ,IDX)) (safe-incf (,(NTH 0 X) ,(NTH 1 X) ,IDX) ,INC ,WHERE)))) (t (let ((v (make-symbol "V"))) `(let ((,V (the-mfixnum ,X))) (declare (type mfixnum ,V)) (cond ((<= ,V (the-mfixnum (- most-positive-mfixnum (the-mfixnum ,INC)))) (setf (the mfixnum ,X) (the-mfixnum (+ ,V (the-mfixnum ,INC)))) nil) (t (safe-incf-aux-error ,X ,INC ,WHERE))))))))
safe-incfmacro
(defmacro safe-incf (x inc &optional where) (cond ((integerp inc) (if (<= inc 0) nil `(safe-incf-aux ,X ,INC ,WHERE))) ((symbolp inc) `(if (>= 0 (the-mfixnum ,INC)) nil (safe-incf-aux ,X ,INC ,WHERE))) (t (let ((incv (make-symbol "INCV"))) `(let ((,INCV (the-mfixnum ,INC))) (declare (type mfixnum ,INCV)) (if (>= 0 ,INCV) nil (safe-incf-aux ,X ,INCV ,WHERE)))))))
incf-pons-callsmacro
(defmacro incf-pons-calls nil '(safe-incf *pons-call-counter* 1))
incf-pons-missesmacro
(defmacro incf-pons-misses nil '(safe-incf *pons-misses-counter* 1))
ponsfunction
(defun pons (x y ht) (declare (hash-table ht)) (incf-pons-calls) (let* ((flex-alist (mf-gethash y ht)) (entry (hl-flex-assoc x flex-alist))) (cond (entry) (t (incf-pons-misses) (let* ((was-alistp (listp flex-alist)) (new-cons (cons x y)) (new-flex-alist (mf-flex-acons new-cons flex-alist))) (when was-alistp (mf-sethash y new-flex-alist ht)) new-cons)))))
pist*macro
(defmacro pist* (table &rest x) (cond ((atom x) x) ((atom (cdr x)) (car x)) (t (list 'pons (car x) (cons 'pist* (cons table (cdr x))) table))))
initialize-never-memoize-htfunction
(defun initialize-never-memoize-ht nil (let ((ht (mf-mht :test 'eq :shared :default))) (note-fns-in-file "hons-raw.lisp" ht) (note-fns-in-file "memoize-raw.lisp" ht) (flet ((update-nmht (fn) (when (and (fboundp fn) (not (macro-function fn))) (never-memoize-fn fn)))) (mf-maphash (lambda (key val) (declare (ignore val)) (update-nmht key)) ht) (loop for fn in *common-lisp-symbols-from-main-lisp-package* do (update-nmht fn)))) nil)
never-memoize-fnfunction
(defun never-memoize-fn (fn) (mf-sethash fn t *never-memoize-ht*) nil)
never-memoize-pfunction
(defun never-memoize-p (fn) (mf-gethash fn *never-memoize-ht*))
other
(defrec memoize-info-ht-entry (ext-anc-attachments start-ticks num tablename ponstablename condition inline memoized-fn old-fn fn sts cl-defun formals commutative specials stobjs-in stobjs-out record-bytes record-calls record-hits record-mht-calls record-pons-calls record-time forget memo-table-init-size aokp invoke) t)
ma-indexmacro
(defmacro ma-index (col &optional (row 0) (2mmf '*2max-memoize-fns*)) (let ((col-base `(* ,2MMF (the-mfixnum ,COL)))) (if (eql row 0) `(the-mfixnum ,COL-BASE) `(ma-index-from-col-base ,COL-BASE ,ROW))))
ma-index-from-col-basemacro
(defmacro ma-index-from-col-base (col-base row) `(the-mfixnum (+ (the-mfixnum ,COL-BASE) (the-mfixnum ,ROW))))
ma-index-callsmacro
(defmacro ma-index-calls (child &optional (parent 0) (2mmf '*2max-memoize-fns*)) (let ((2child `(the-mfixnum (* 2 (the-mfixnum ,CHILD))))) (if (eql parent 0) 2child `(ma-index ,PARENT ,2CHILD ,2MMF))))
ma-index-ticksmacro
(defmacro ma-index-ticks (child &optional (parent 0) (2mmf '*2max-memoize-fns*)) (let ((2child+1 `(the-mfixnum (1+ (the-mfixnum (* 2 (the-mfixnum ,CHILD))))))) (if (eql parent 0) 2child+1 `(ma-index ,PARENT ,2CHILD+1 ,2MMF))))
outside-caller-col-basefunction
(defun outside-caller-col-base nil (ma-index *initial-max-symbol-to-fixnum*))
other
(defvar *caller* (let ((val (outside-caller-col-base))) (check-type val mfixnum) val))
other
(declaim (type mfixnum *caller*))
other
(defparameter *memoize-verbose* nil)
memoize-table-desired-sizefunction
(defun memoize-table-desired-size (fn min-size) (let* ((max-sizes (mf-gethash fn *memo-max-sizes*))) (if (not max-sizes) min-size (let* ((nclears (access memo-max-sizes-entry max-sizes :num-clears)) (avg-mt-size (access memo-max-sizes-entry max-sizes :avg-mt-size)) (our-guess (ceiling (* 1.2 avg-mt-size))) (capped-guess (min our-guess (* nclears 44000))) (final-guess (max *mht-default-size* min-size capped-guess))) (when (and (< (integer-length (- nclears 1)) (integer-length nclears)) *memoize-verbose*) (format t "; ~s memo table: ~s clears, avg size ~s, guess ~s, final ~ ~s~%" fn nclears avg-mt-size our-guess final-guess)) final-guess))))
pons-table-desired-sizefunction
(defun pons-table-desired-size (fn min-size) (let* ((max-sizes (mf-gethash fn *memo-max-sizes*))) (if (not max-sizes) *mht-default-size* (let* ((nclears (access memo-max-sizes-entry max-sizes :num-clears)) (avg-pt-size (access memo-max-sizes-entry max-sizes :avg-pt-size)) (our-guess (ceiling (* 1.2 avg-pt-size))) (capped-guess (min our-guess (* nclears 44000))) (final-guess (max *mht-default-size* min-size capped-guess))) (when (and (< (integer-length (- nclears 1)) (integer-length nclears)) *memoize-verbose*) (format t "; ~s pons table: ~s clears, avg size ~s, guess ~s, final ~ ~s~%" fn nclears avg-pt-size our-guess final-guess)) final-guess))))
make-initial-memoize-hash-tablefunction
(defun make-initial-memoize-hash-table (fn init-size) (with-global-memoize-lock (mf-mht :size (memoize-table-desired-size fn init-size))))
make-initial-memoize-pons-tablefunction
(defun make-initial-memoize-pons-table (fn init-size) (with-global-memoize-lock (mf-mht :size (pons-table-desired-size fn init-size))))
update-memo-max-sizesfunction
(defun update-memo-max-sizes (fn pt-size mt-size) (when (or (< 0 mt-size) (< 0 pt-size)) (with-global-memoize-lock (let ((old (mf-gethash fn *memo-max-sizes*))) (if (not old) (mf-sethash fn (make memo-max-sizes-entry :num-clears 1 :max-pt-size pt-size :max-mt-size mt-size :avg-pt-size (coerce pt-size 'float) :avg-mt-size (coerce mt-size 'float)) *memo-max-sizes*) (let* ((old.num-clears (access memo-max-sizes-entry old :num-clears)) (old.max-pt-size (access memo-max-sizes-entry old :max-pt-size)) (old.max-mt-size (access memo-max-sizes-entry old :max-mt-size)) (old.avg-pt-size (access memo-max-sizes-entry old :avg-pt-size)) (old.avg-mt-size (access memo-max-sizes-entry old :avg-mt-size)) (new.num-clears (+ 1 old.num-clears))) (mf-sethash fn (make memo-max-sizes-entry :num-clears new.num-clears :max-pt-size (max pt-size old.max-pt-size) :max-mt-size (max mt-size old.max-mt-size) :avg-pt-size (/ (+ pt-size (* old.avg-pt-size old.num-clears)) new.num-clears) :avg-mt-size (/ (+ mt-size (* old.avg-mt-size old.num-clears)) new.num-clears)) *memo-max-sizes*)))))) nil)
print-memo-max-sizesfunction
(defun print-memo-max-sizes nil (with-global-memoize-lock (when (equal (mf-hash-table-count *memo-max-sizes*) 0) (return-from print-memo-max-sizes nil)) (format t "Memo table statistics gathered at each from when they were ~ cleared:~%~%") (let ((indent 8) indent-str) (mf-maphash (lambda (fn entry) (declare (ignore entry)) (setq indent (max indent (length (symbol-name fn))))) *memo-max-sizes*) (setq indent-str (format nil "~a" (+ 2 indent))) (format t (concatenate 'string "~" indent-str ":@a") "Function") (format t " ~10:@a | ~15:@a ~15:@a | ~15:@a ~15:@a~%" "Clears" "PT Max" "PT Avg" "MT Max" "MT Avg") (mf-maphash (lambda (fn entry) (let* ((num-clears (access memo-max-sizes-entry entry :num-clears)) (max-pt-size (access memo-max-sizes-entry entry :max-pt-size)) (max-mt-size (access memo-max-sizes-entry entry :max-mt-size)) (avg-pt-size (access memo-max-sizes-entry entry :avg-pt-size)) (avg-mt-size (access memo-max-sizes-entry entry :avg-mt-size))) (format t (concatenate 'string "~" indent-str ":@a ~10:D | ~15:D ~15:D | ~15:D ~15:D~%") fn num-clears max-pt-size (floor avg-pt-size) max-mt-size (floor avg-mt-size)))) *memo-max-sizes*) (format t "~%"))) nil)
memoize-flush1function
(defun memoize-flush1 (lst) (with-global-memoize-lock (loop for sym in lst do (when (boundp (the symbol sym)) (let ((old (symbol-value (the symbol sym)))) (unless (or (null old) (eql 0 (mf-hash-table-count old))) (setf (symbol-value (the symbol sym)) nil)))))))
memoize-flushmacro
(defmacro memoize-flush (st) (and st (let ((s (st-lst st))) `(when ,S (memoize-flush1 ,S)))))
sync-memoize-call-arrayfunction
(defun sync-memoize-call-array nil (with-global-memoize-lock (let ((n1 (ma-index *2max-memoize-fns*)) (n2 (1+ *max-symbol-to-fixnum*))) (declare (type (and fixnum mfixnum) n1 n2)) (setq *memoize-call-array* (initial-memoize-call-array 1)) (setq *callers-array* (make-array 0)) (gc$) (setq *memoize-call-array* (initial-memoize-call-array n1)) (setq *callers-array* (make-array n2 :initial-element nil)) (setq *caller* (outside-caller-col-base)))))
memoize-call-array-growfunction
(defun memoize-call-array-grow (&optional (2nmax (* 2 (ceiling (* 3/2 (/ *2max-memoize-fns* 2)))))) (with-global-memoize-lock (unless (integerp 2nmax) (error "(memoize-call-array-grow ~s). Arg must be an integer." 2nmax)) (unless (evenp 2nmax) (error "(memoize-call-array-grow ~s). Arg must be even." 2nmax)) (unless (> 2nmax 100) (error "(memoize-call-array-grow ~s). Arg must be > 100." 2nmax)) (when (<= 2nmax *2max-memoize-fns*) (cw "; memoize-call-array-grow: *memoize-call-array* already big enough.~%") (return-from memoize-call-array-grow)) (unless (<= (* 2nmax 2nmax) most-positive-mfixnum) (error "memoize-call-array-grow: most-positive-mfixnum exceeded. Too ~ many memoized functions.")) (unless (<= (* 2nmax 2nmax) most-positive-fixnum) (error "memoize-call-array-grow: most-positive-fixnum exceeded. Too ~ many memoized functions.")) (unless (< (* 2nmax 2nmax) array-total-size-limit) (error "memoize-call-array-grow: ARRAY-TOTAL-SIZE-LIMIT exceeded. Too ~ many memoized functions.")) (unless (< (* 2nmax 2nmax) array-dimension-limit) (error "memoize-call-array-grow: ARRAY-DIMENSION-LIMIT exceeded. Too ~ many memoized functions.")) (unless (eql *caller* (outside-caller-col-base)) (cerror "Continue at your own risk." "MEMOIZE-CALL-ARRAY-GROW was called while a memoized function~%~ was executing, so all bets are off. Continue only at your own~%~ risk. That risk may be low, but at the least, memoization~%~ reports (in particular, from memsum) will probably be~%~ inaccurate.")) (setq *2max-memoize-fns* 2nmax) (let ((state *the-live-state*)) (observation 'memoize-call-array-grow "Now reinitializing memoization structures. This will ~ erase saved values and statistics.")) (sync-memoize-call-array) (rememoize-all)) nil)
other
(defun-one-output symbol-to-fixnum-create (s) (check-type s symbol) (with-global-memoize-lock (let ((g (mf-gethash s *memoize-info-ht*))) (if g (access memoize-info-ht-entry g :num) (let (new) (loop for i fixnum from (1+ *initial-max-symbol-to-fixnum*) below (the fixnum (floor *2max-memoize-fns* 2)) do (unless (mf-gethash i *memoize-info-ht*) (setq new i) (return))) (cond (new (setq *max-symbol-to-fixnum* (max *max-symbol-to-fixnum* new)) new) (t (memoize-call-array-grow) (symbol-to-fixnum-create s))))))))
other
(defun-one-output symbol-to-fixnum (s) (check-type s symbol) (let ((g (mf-gethash s *memoize-info-ht*))) (if g (access memoize-info-ht-entry g :num) (error "(symbol-to-fixnum ~s). Illegal symbol." s))))
other
(defun-one-output fixnum-to-symbol (n) (check-type n fixnum) (or (mf-gethash n *memoize-info-ht*) (error "(fixnum-to-symbol ~s). Illegal number." n)))
other
(defun-one-output hons-gentemp (root) (check-type root string) (loop (safe-incf *hons-gentemp-counter* 1 hons-gentemp) (let ((name (our-syntax (format nil "HONS-G-~s,~s" root *hons-gentemp-counter*)))) (multiple-value-bind (sym status) (intern name (find-package "ACL2_INVISIBLE")) (if (null status) (return sym))))))
other
(defun-one-output st-lst (st) (check-type st symbol) (intern (our-syntax (format nil "HONS-S-~s,~s" (package-name (symbol-package st)) (symbol-name st))) (find-package "ACL2_INVISIBLE")))
other
(defun-one-output mf-dcls
(l)
(loop for
dec
in
l
nconc
(let ((temp (if (consp dec)
(loop for
d
in
(cdr dec)
nconc
(if (and (consp d) (eq (car d) 'ignore))
nil
(cons d nil))))))
(if temp
(cons (cons 'declare temp) nil)))))
memoize-use-attachment-warningfunction
(defun memoize-use-attachment-warning (fn at-fn) (when *memoize-use-attachment-warning-p* (let ((state *the-live-state*)) (warning$ 'top-level "Attachment" "Although the function ~x0 is memoized, a result is not being ~ stored because ~@1. Warnings such as this one, about not ~ storing results, will remain off for all functions for the ~ remainder of the session unless the variable ~x2 is set to a ~ non-nil value in raw Lisp." fn (mv-let (lookup-p at-fn) (if (consp at-fn) (assert$ (eq (car at-fn) :lookup) (mv t (cdr at-fn))) (mv nil at-fn)) (cond (lookup-p (msg "a stored result was used from a call of ~ memoized function ~x0, which may have ~ been computed using attachments" at-fn)) ((eq at-fn :|{APPLY$-OR-BADGE}-USERFN|) (msg "one of the functions ~v0, which depend ~ on warrants for the result, was called ~ during evaluation of a call of ~x1" '(apply$-userfn badge-userfn) fn)) (t (msg "an attachment to function ~x0 was used ~ during evaluation of one of its calls" at-fn)))) '*memoize-use-attachment-warning-p*)) (setq *memoize-use-attachment-warning-p* nil)))
other
(defun-one-output memoize-fn-suffix (str sym) (check-type str string) (check-type sym symbol) (let ((spkn (package-name (symbol-package sym))) (sn (symbol-name sym))) (format nil "~s,~s,~s" str spkn sn)))
mf-indexmacro
(defmacro mf-index (x &optional known-not-rational) (assert (symbolp x)) `(cond ,@(UNLESS KNOWN-NOT-RATIONAL `(((TYPEP ,X 'FIXNUM) ,X)))))
other
(defun-one-output mis-ordered-commutative-args (x y) (cond ((eql x y) nil) (t (let ((idx (mf-index x))) (declare (type (or null fixnum) idx)) (cond (idx (let ((idy (mf-index y))) (declare (type (or null fixnum) idy)) (cond (idy (< (the fixnum idy) (the fixnum idx))) ((rationalp y) (< y (the fixnum idx)))))) ((rationalp x) (let ((idy (mf-index y))) (declare (type (or null fixnum) idy)) (cond (idy (< (the fixnum idy) x)) ((rationalp y) (< y x))))) ((or (rationalp y) (mf-index y t))))))))
memoize-look-up-deffunction
(defun memoize-look-up-def (fn cl-defun inline wrld &key quiet-p) (cond ((eq cl-defun :default) (cond ((null inline) nil) ((not (fboundp fn)) (error "MEMOIZE-LOOK-UP-DEF: ** ~a is undefined." fn)) ((let ((def (cltl-def-from-name fn wrld))) (cond (def (assert (eq (car def) 'defun)) (cdr def))))) (t (memoize-look-up-def-raw fn quiet-p)))) ((eq (car cl-defun) 'defun) (cdr cl-defun)) (t cl-defun)))
other
(defg *memoize-timing-bugs* 0)
fix-ticksmacro
(defmacro fix-ticks (ticks ctx) `(let ((ticks ,TICKS) (ctx ,CTX)) (declare (type mfixnum ticks)) (the-mfixnum (cond ((and (<= 0 (the-mfixnum ticks)) (< (the-mfixnum ticks) (the-mfixnum *10-days*))) (the-mfixnum ticks)) (t (incf *memoize-timing-bugs*) (when (<= *memoize-timing-bugs* 10) (format t "Ignoring time increment of ~a sec for ~a~%" (/ ticks *float-ticks/second*) ctx) (when (eql *memoize-timing-bugs* 10) (format t "Timing is very dubious. Suppressing further messages.~%"))) 0)))))
other
(defun-one-output memoizedp-raw (fn) (and (symbolp fn) (values (mf-gethash fn *memoize-info-ht*))))
mf-make-symbolmacro
(defmacro mf-make-symbol (&rest r) `(our-syntax (intern (format nil ,@R) *acl2-package*)))
memoize-fn-initfunction
(defun memoize-fn-init (fn inline wrld &aux (state *the-live-state*)) (with-global-memoize-lock (unless (symbolp fn) (error "Memoize-fn: ~s is not a symbol." fn)) (maybe-untrace! fn) (unless *memoize-init-done* (error "Memoize-fn: *MEMOIZE-INIT-DONE* is still nil.")) (unless (fboundp fn) (error "Memoize-fn: ~s is not fboundp." fn)) (when (or (macro-function fn) (special-operator-p fn) (and (fboundp 'compiler-macro-function) (compiler-macro-function fn))) (error "Memoize-fn: ~s is a macro or a special operator or has a ~ compiler macro." fn)) (when (never-memoize-p fn) (error "Memoize-fn: ~s must never be memoized" fn)) (when (and inline (or (member-eq fn (f-get-global 'logic-fns-with-raw-code state)) (member-eq fn (f-get-global 'program-fns-with-raw-code state)))) (error "Memoize-fn: ~s must never be memoized with :inline t,~%~ because it belongs to the list stored in state global~%~ variable ~s and thus runs code different~%~ than that stored in the ACL2 logical world, as is typically~%~ used when inserting inlined code for memoization." fn (if (member-eq fn (f-get-global 'logic-fns-with-raw-code state)) 'logic-fns-with-raw-code 'program-fns-with-raw-code))) (when (memoizedp-raw fn) (observation 'memoize "~s0 is currently memoized. We will first unmemoize it, ~ then memoize it again." fn) (unmemoize-fn fn)) (when (member fn (eval '(trace))) (observation 'memoize "Untracing ~s before memoizing it." fn) (eval `(untrace ,FN))) (when (and (fboundp 'old-trace) (member fn (eval '(old-trace)))) (observation 'memoize "Old-untracing ~s before memoizing it." fn) (eval `(old-untrace ,FN))) (when (getpropc fn 'constrainedp nil wrld) (error "Memoize-fn: ~s is constrained; you may instead wish to memoize a ~ caller or to memoize its attachment (see :DOC defattach)." fn))))
memoize-fn-init-2function
(defun memoize-fn-init-2 (fn formals condition stobjs-in stobjs-out) (unless (and (symbol-listp formals) (no-duplicatesp formals) (loop for x in formals never (constantp x))) (error "Memoize-fn: FORMALS, ~a, must be a true list of distinct, ~ nonconstant symbols." formals)) (when (intersection lambda-list-keywords formals) (error "Memoize-fn: FORMALS, ~a, may not intersect LAMBDA-LIST-KEYWORDS." formals)) (when (and condition (or (member 'state stobjs-in) (member 'state stobjs-out))) (error "Memoize-fn: ~s uses STATE." fn)))
memoize-fn-inner-bodyfunction
(defun memoize-fn-inner-body (fn condition body fn-col-base tablename localtablename ponstablename localponstablename memo-table-init-size formals specials stobjs-out number-of-args commutative aokp prog1-fn) (let ((mf-record-mht (and *record-mht-calls* `((safe-incf (aref ,*MF-MA* ,(MA-INDEX-FROM-COL-BASE FN-COL-BASE *MA-MHT-INDEX*)) 1)))) (mf-record-hit (and *record-hits* condition `((safe-incf (aref ,*MF-MA* ,(MA-INDEX-FROM-COL-BASE FN-COL-BASE *MA-HITS-INDEX*)) 1))))) `(cond ,@(AND (NOT (MEMBER-EQUAL CONDITION '('T T))) `(((NOT ,CONDITION) ,@(AND *CONDITION-NIL-AS-HIT* MF-RECORD-HIT) ,BODY))) ,@(AND CONDITION `((T (LET (,*MF-ANS* ,*MF-ARGS* ,*MF-ANS-P*) (DECLARE (IGNORABLE ,*MF-ANS* ,*MF-ARGS* ,*MF-ANS-P*)) (WHEN (NULL ,TABLENAME) ,@MF-RECORD-MHT (SETQ ,TABLENAME (MAKE-INITIAL-MEMOIZE-HASH-TABLE ',FN ,MEMO-TABLE-INIT-SIZE))) (SETQ ,LOCALTABLENAME ,TABLENAME) ,@(AND (> NUMBER-OF-ARGS 1) `((WHEN (NULL ,PONSTABLENAME) (SETQ ,PONSTABLENAME (MAKE-INITIAL-MEMOIZE-PONS-TABLE ',FN ,MEMO-TABLE-INIT-SIZE))) (SETQ ,LOCALPONSTABLENAME ,PONSTABLENAME))) (SETQ ,*MF-ARGS* ,(COND (COMMUTATIVE `(COND ((MIS-ORDERED-COMMUTATIVE-ARGS ,(CAR FORMALS) ,(CADR FORMALS)) (PIST* ,LOCALPONSTABLENAME ,(CADR FORMALS) ,(CAR FORMALS) ,@SPECIALS)) (T (PIST* ,LOCALPONSTABLENAME ,(CAR FORMALS) ,(CADR FORMALS) ,@SPECIALS)))) (T `(PIST* ,LOCALPONSTABLENAME ,@FORMALS ,@SPECIALS)))) (MULTIPLE-VALUE-SETQ (,*MF-ANS* ,*MF-ANS-P*) ,(LET ((GETHASH-FORM `(MF-GETHASH ,*MF-ARGS* ,LOCALTABLENAME))) (COND (AOKP `(COND (*AOKP* ,GETHASH-FORM) (T (VALUES NIL NIL)))) (T GETHASH-FORM)))) (COND (,*MF-ANS-P* ,@(AND AOKP `((UPDATE-ATTACHED-FN-CALLED ',(CONS :LOOKUP FN)))) ,@MF-RECORD-HIT ,@(COND ((NULL (CDR STOBJS-OUT)) `(,*MF-ANS*)) (T (LET ((LEN-1 (1- (LENGTH STOBJS-OUT)))) `(,(CONS 'MV (NCONC (LOOP FOR I FIXNUM BELOW LEN-1 COLLECT `(POP ,*MF-ANS*)) (LIST *MF-ANS*)))))))) (T ,(LET* ((VARS (LOOP FOR I FIXNUM BELOW (IF (CDR STOBJS-OUT) (LENGTH STOBJS-OUT) 1) COLLECT (MF-MAKE-SYMBOL "O~a" I)))) (COND (AOKP `(MV?-LET ,VARS ,BODY (PROGN (MF-SETHASH ,*MF-ARGS* (LIST* ,@VARS) ,LOCALTABLENAME) (MV? ,@VARS)))) (T `(LET (,*ATTACHED-FN-TEMP*) (MV?-LET ,VARS (LET ((*AOKP* (AND *AOKP* T)) (SAVED-WARRANT-REQS *WARRANT-REQS*)) (WHEN (CONSP SAVED-WARRANT-REQS) (SETQ *WARRANT-REQS* (AND SAVED-WARRANT-REQS T))) (,PROG1-FN ,BODY (COND ((NOT (MEMBER *AOKP* '(T NIL) :TEST #'EQ)) (SETQ ,*ATTACHED-FN-TEMP* *AOKP*)) ((CONSP *WARRANT-REQS*) (SETQ ,*ATTACHED-FN-TEMP* :{APPLY$-OR-BADGE}-USERFN) (WHEN (CONSP SAVED-WARRANT-REQS) (SETQ *WARRANT-REQS* (UNION-EQ *WARRANT-REQS* SAVED-WARRANT-REQS)))) ((EQ SAVED-WARRANT-REQS T) (SETQ *WARRANT-REQS* T))))) (PROGN (COND (,*ATTACHED-FN-TEMP* (MEMOIZE-USE-ATTACHMENT-WARNING ',FN ,*ATTACHED-FN-TEMP*)) (T (MF-SETHASH ,*MF-ARGS* (LIST* ,@VARS) ,LOCALTABLENAME))) (WHEN ,*ATTACHED-FN-TEMP* (ASSERT (OR *AOKP* (EQ ,*ATTACHED-FN-TEMP* :{APPLY$-OR-BADGE}-USERFN))) (UPDATE-ATTACHED-FN-CALLED ,*ATTACHED-FN-TEMP*)) (MV? ,@VARS))))))))))))))))
memoize-fn-outer-bodyfunction
(defun memoize-fn-outer-body (inner-body fn fn-col-base start-ticks forget prog1-fn) `(let (,@(AND *RECORD-BYTES* `((,*MF-START-BYTES* (HEAP-BYTES-ALLOCATED)))) ,@(AND *RECORD-PONS-CALLS* `((,*MF-START-PONS* *PONS-CALL-COUNTER*))) (,START-TICKS ,(IF *RECORD-TIME* '(INTERNAL-REAL-TICKS) '0))) (declare (ignorable ,@(AND *RECORD-BYTES* `(,*MF-START-BYTES*)) ,@(AND *RECORD-PONS-CALLS* `(,*MF-START-PONS*))) (type mfixnum ,START-TICKS ,@(AND *RECORD-PONS-CALLS* `(,*MF-START-PONS*)) ,@(AND *RECORD-BYTES* `(,*MF-START-BYTES*)))) (,(COND ((OR *RECORD-PONS-CALLS* *RECORD-BYTES* *RECORD-TIME* FORGET) (IF (F-GET-GLOBAL 'PROTECT-MEMOIZE-STATISTICS *THE-LIVE-STATE*) 'UNWIND-PROTECT-DISABLE-INTERRUPTS-DURING-CLEANUP PROG1-FN)) (T 'PROGN)) ,(COND ((OR *RECORD-BYTES* *RECORD-CALLS* *RECORD-HITS* *RECORD-MHT-CALLS* *RECORD-PONS-CALLS* *RECORD-TIME*) `(LET ((*CALLER* ,FN-COL-BASE)) ,INNER-BODY)) (T INNER-BODY)) ,@(AND *RECORD-PONS-CALLS* `((SAFE-INCF (AREF ,*MF-MA* ,(MA-INDEX-FROM-COL-BASE FN-COL-BASE *MA-PONS-INDEX*)) (THE-MFIXNUM (- *PONS-CALL-COUNTER* ,*MF-START-PONS*))))) ,@(AND *RECORD-BYTES* `((SAFE-INCF (AREF ,*MF-MA* ,(MA-INDEX-FROM-COL-BASE FN-COL-BASE *MA-BYTES-INDEX*)) (THE-MFIXNUM (- (HEAP-BYTES-ALLOCATED) ,*MF-START-BYTES*))))) ,@(AND *RECORD-TIME* `((SAFE-INCF (THE MFIXNUM (AREF ,*MF-MA* (THE-MFIXNUM (1+ ,*MF-COUNT-LOC*)))) (THE-MFIXNUM (FIX-TICKS (THE-MFIXNUM (- (INTERNAL-REAL-TICKS) ,START-TICKS)) ',FN))))) ,@(AND FORGET `((CLEAR-MEMOIZE-TABLE ',FN))))))
memoize-fn-deffunction
(defun memoize-fn-def (inner-body outer-body fn formals specials dcls fnn start-ticks localtablename localponstablename) `(defun ,FN ,FORMALS ,@DCLS (declare (ignorable ,@FORMALS ,@SPECIALS)) (with-global-memoize-lock-static (let* ((,*MF-COUNT-LOC* ,(IF (OR *RECORD-CALLS* *RECORD-TIME*) `(THE-MFIXNUM (+ *CALLER* ,(* 2 FNN))) 0)) (,*MF-MA* *memoize-call-array*) ,LOCALTABLENAME ,LOCALPONSTABLENAME) (declare (type mfixnum ,*MF-COUNT-LOC*) (ignorable ,*MF-COUNT-LOC* ,*MF-MA* ,LOCALPONSTABLENAME ,LOCALTABLENAME) (type (simple-array mfixnum (*)) ,*MF-MA*)) ,@(AND *RECORD-CALLS* `((SAFE-INCF (AREF ,*MF-MA* ,*MF-COUNT-LOC*) 1))) (if (eql -1 ,START-TICKS) ,OUTER-BODY ,INNER-BODY)))))
other
(defun-one-output memoize-eval-compile (def old-fn) (declare (ignore old-fn)) (unless (and (consp def) (eq 'defun (car def)) (consp (cdr def)) (symbolp (cadr def))) (error "MEMOIZE-EVAL-COMPILE: Bad input:~%~s." def)) (compile (eval def)) nil)
memoize-fn-formalsfunction
(defun memoize-fn-formals (fn wrld inline &key (cl-defun :default cl-defun-p)) (let ((formals (getpropc fn 'formals t wrld))) (if (eq formals t) (let ((cl-defun (if cl-defun-p cl-defun (memoize-look-up-def fn cl-defun inline wrld :quiet-p t)))) (if (consp cl-defun) (cadr cl-defun) (let ((n (mf-len-inputs fn))) (if n (loop for i fixnum below n collect (mf-make-symbol "X~a" i)) t)))) formals)))
cltl-def-memoize-invokefunction
(defun cltl-def-memoize-invoke (fn-def old-fn invoke) (let ((gsym (gensym)) (fn (car fn-def)) (formals (cadr fn-def)) (decls (butlast (cddr fn-def) 1))) (eval `(defvar ,GSYM nil)) `(,FN ,FORMALS ,@DECLS (if ,GSYM (funcall ,OLD-FN ,@FORMALS) (let ((,GSYM t)) (,INVOKE ,@FORMALS))))))
memoize-fnfunction
(defun memoize-fn (fn &key (condition t) (inline t) (cl-defun :default) (formals :default) (stobjs-in :default) (specials nil) (commutative nil) (stobjs-out :default) (forget nil) (memo-table-init-size *mht-default-size*) (aokp nil) (invoke nil) &aux (wrld (w *the-live-state*)) (memoize-fn-signature-error "Memoize-fn: could not determine a signature for ~a.~%~ To assert the signature of ~:*~a, use (mf-note-arity '~:*~a nargs nvals),~%~ for example, (mf-note-arity '~:*~a 3 1).) If there are stobjs arguments~%~ then do not use that mechanism; instead, pass suitable arguments to~%~ memoize-fn.")) "The documentation for MEMOIZE-FN is very incomplete. One may invoke (MEMOIZE-FN fn) on the name of a Common Lisp function FN from outside the ACL2 loop to get results of possible interest in terms of memoization activity and profiling information. MEMOIZE-FN already has a dozen parameters. MEMOIZE-FN replaces the SYMBOL-FUNCTION for the symbol FN with 'enhanced' raw Common Lisp code that, supposedly, does not affect the value returned by FN but may make some notes and may even obtain some return values by remembering them from a previous call. If the CONDITION parameter is not NIL or 'NIL, then whenever FN is called, and there is not as yet any value remembered for a call of FN on the given arguments, then if the evaluation of the CONDITION parameter (where the formals of FN are bound to its actuals) is not NIL or 'NIL, the values that are computed for FN on the given arguments will be saved under the given arguments. If the INLINE parameter is T, then when MEMOIZE-FN creates a new body for FN, we place the old body of FN within the new body, i.e., 'in line'. However, if the INLINE parameter is NIL, then we place code that calls the existing SYMBOL-FUNCTION for FN within the new body. One might well argue that our parity for the INLINE parameter to MEMOIZE-fn is backwards, but we don't think so. One may lie to MEMOIZE-FN to force the memoization of a function that has ACL2's state as an explicit parameter by using fraudulent FORMALS, STOBJS-IN, and STOBJS-OUT parameters to MEMOIZE-FN. If the COMMUTATIVE parameter is not NIL, then the two arguments may be swapped before further processing. We hope/presume that ACL2 will have been used first to prove that commutativity. If the CL-DEFUN parameter is not NIL, we pretend that the current body of FN is that parameter, and similarly for FORMALS, STOBJS-IN, and STOBJS-OUT. If FN is a raw Common Lisp function and not an ACL2-approved function, it may make reference to a variable, say S, that has a SPECIAL binding, in which case one needs to consider what in the world the meaning is for memoizing such a function at all. If S is a member of the SPECIALS parameter, then it is assumed that FN does not alter but only refers to S. MEMOIZE-FN acts as though FN had S as an extra argument for purposes of memoization. If the FORGET parameter is not NIL, the pons and memo tables of FN are discarded at the end of every outermost call of FN." (when (equal condition *nil*) (setq condition nil)) (with-global-memoize-lock (with-warnings-suppressed (memoize-fn-init fn inline wrld) (let* ((cl-defun0 (memoize-look-up-def fn cl-defun inline wrld)) (old-fn (symbol-function fn)) (cl-defun (if invoke (cltl-def-memoize-invoke cl-defun0 old-fn invoke) cl-defun0)) (formals (cond ((eq formals :default) (let ((formals (memoize-fn-formals fn wrld inline :cl-defun cl-defun))) (if (eq formals t) (error memoize-fn-signature-error fn) formals))) (t formals))) (stobjs-in (if (eq stobjs-in :default) (let ((s (getpropc fn 'stobjs-in t wrld))) (if (eq s t) (make-list (len formals)) s)) stobjs-in)) (stobjs-out (if (eq stobjs-out :default) (let ((s (getpropc fn 'stobjs-out t wrld))) (if (eq s t) (let ((n (mf-len-outputs fn))) (cond (n (make-list n)) ((null condition) (list nil)) (t (error memoize-fn-signature-error fn)))) s)) stobjs-out))) (memoize-fn-init-2 fn formals condition stobjs-in stobjs-out) (mf-sethash fn (cons (length stobjs-in) (length stobjs-out)) *number-of-arguments-and-values-ht*) (let* ((fnn (symbol-to-fixnum-create fn)) (fn-col-base (ma-index fnn)) (body (progn (assert old-fn) (cond (invoke (car (last cl-defun))) (inline (assert (consp cl-defun)) (car (last cl-defun))) (t `(funcall ,OLD-FN ,@FORMALS))))) (dcls (mf-dcls (cddr (butlast cl-defun)))) (start-ticks (let ((v (hons-gentemp (memoize-fn-suffix "START-TICKS-" fn)))) (eval `(prog1 (defparameter ,V -1) (declaim (type mfixnum ,V)))))) (tablename (eval `(defg ,(HONS-GENTEMP (MEMOIZE-FN-SUFFIX "MEMOIZE-HT-FOR-" FN)) nil))) (ponstablename (eval `(defg ,(HONS-GENTEMP (MEMOIZE-FN-SUFFIX "PONS-HT-FOR-" FN)) nil))) (localtablename (make-symbol "TABLENAME")) (localponstablename (make-symbol "PONSTABLENAME")) (sts (and condition (remove-duplicates-eq (loop for st in (union stobjs-in stobjs-out) when (and st (not (eq st :df))) collect (assert$ (not (eq st 'state)) (st-lst (congruent-stobj-rep (or (concrete-stobj st wrld) st) wrld))))))) (number-of-args (+ (len formals) (len specials))) (prog1-fn (if (cdr stobjs-out) 'multiple-value-prog1 'prog1)) (inner-body (memoize-fn-inner-body fn condition body fn-col-base tablename localtablename ponstablename localponstablename memo-table-init-size formals specials stobjs-out number-of-args commutative aokp prog1-fn)) (outer-body (memoize-fn-outer-body inner-body fn fn-col-base start-ticks forget prog1-fn)) (def (memoize-fn-def inner-body outer-body fn formals specials dcls fnn start-ticks localtablename localponstablename)) (success nil)) (unwind-protect (progn (let ((ma *memoize-call-array*)) (declare (type (simple-array mfixnum (*)) ma)) (loop for i of-type mfixnum from fn-col-base below (ma-index-from-col-base fn-col-base *2max-memoize-fns*) unless (eql (aref ma i) 0) do (setf (aref ma i) 0))) (memoize-eval-compile def old-fn) (mf-sethash fn (make memoize-info-ht-entry :ext-anc-attachments (and aokp (ext-ancestors-attachments fn wrld)) :start-ticks start-ticks :num fnn :tablename tablename :ponstablename ponstablename :condition condition :inline inline :memoized-fn (symbol-function fn) :old-fn old-fn :fn fn :sts sts :cl-defun cl-defun :formals formals :commutative commutative :specials specials :stobjs-in stobjs-in :stobjs-out stobjs-out :record-bytes *record-bytes* :record-calls *record-calls* :record-hits *record-hits* :record-mht-calls *record-mht-calls* :record-pons-calls *record-pons-calls* :record-time *record-time* :forget forget :memo-table-init-size memo-table-init-size :aokp aokp :invoke invoke) *memoize-info-ht*) (mf-sethash fnn fn *memoize-info-ht*) (and condition (loop for s in sts do (push tablename (symbol-value (the symbol s))))) (setq success t)) (unless success (without-interrupts (setf (symbol-function fn) old-fn) (remhash fn *memoize-info-ht*) (remhash fnn *memoize-info-ht*) (and condition (loop for s in sts when (eq tablename (car (symbol-value (the symbol s)))) do (pop (symbol-value (the symbol s))))) (setq fn nil) (error "Memoize-fn: Failed to memoize ~s." fn)))))))) fn)
other
(defun-one-output unmemoize-fn (fn) (with-global-memoize-lock (maybe-untrace! fn) (let ((rec (memoizedp-raw fn))) (unless rec (error "Unmemoize-fn: ~s is not memoized." fn)) (let* ((num (the-mfixnum (access memoize-info-ht-entry rec :num))) (tablename (access memoize-info-ht-entry rec :tablename)) (ponstablename (access memoize-info-ht-entry rec :ponstablename)) (sts (access memoize-info-ht-entry rec :sts)) (col-base (ma-index num)) (saved-table (symbol-value (the symbol tablename))) (saved-ponstable (symbol-value (the symbol ponstablename))) (saved-fn-entry (mf-gethash fn *memoize-info-ht*)) (saved-num-entry (mf-gethash num *memoize-info-ht*)) (ma *memoize-call-array*) (success nil)) (declare (type mfixnum num col-base) (type (simple-array mfixnum (*)) ma)) (unwind-protect (progn (format nil "unmemoizing ~s" fn) (let nil (let ((old-fn (access memoize-info-ht-entry rec :old-fn))) (assert old-fn) (setf (symbol-function (the symbol fn)) old-fn))) (loop for i of-type mfixnum from col-base below (ma-index-from-col-base col-base *2max-memoize-fns*) unless (eql (aref ma i) 0) do (setf (aref ma i) 0)) (remhash fn *memoize-info-ht*) (remhash num *memoize-info-ht*) (setf (symbol-value (the symbol tablename)) nil) (setf (symbol-value (the symbol ponstablename)) nil) (loop for s in sts do (when (boundp s) (setf (symbol-value (the symbol s)) (remove tablename (symbol-value (the symbol s)))))) (setq success t)) (unless success (without-interrupts (setf (symbol-value (the symbol tablename)) saved-table) (setf (symbol-value (the symbol ponstablename)) saved-ponstable) (mf-sethash fn saved-fn-entry *memoize-info-ht*) (mf-sethash num saved-num-entry *memoize-info-ht*) (loop for s in sts do (when (boundp s) (push tablename (symbol-value (the symbol s))))))))))) fn)
other
(defun-one-output maybe-unmemoize (fn) (with-global-memoize-lock (when (and (memoizedp-raw fn) (not (cdr (assoc-eq fn (table-alist 'memoize-table (w *the-live-state*)))))) (unmemoize-fn fn))))
other
(defun-one-output memoized-functions nil (with-global-memoize-lock (let (ans) (mf-maphash (lambda (fn info) (declare (ignore info)) (when (symbolp fn) (push fn ans))) *memoize-info-ht*) ans)))
other
(defun-one-output length-memoized-functions nil (with-global-memoize-lock (values (floor (1- (mf-hash-table-count *memoize-info-ht*)) 2))))
other
(defun-one-output unmemoize-all
nil
(loop for
x
in
(memoized-functions)
do
(unmemoize-fn x)))
other
(defun-one-output memoize-info (k) (with-global-memoize-lock (let ((v (mf-gethash k *memoize-info-ht*))) (and v (list (list (access memoize-info-ht-entry v :fn) :condition (access memoize-info-ht-entry v :condition) :inline (access memoize-info-ht-entry v :inline) :cl-defun (access memoize-info-ht-entry v :cl-defun) :formals (access memoize-info-ht-entry v :formals) :stobjs-in (access memoize-info-ht-entry v :stobjs-in) :specials (access memoize-info-ht-entry v :specials) :commutative (access memoize-info-ht-entry v :commutative) :stobjs-out (access memoize-info-ht-entry v :stobjs-out) :forget (access memoize-info-ht-entry v :forget) :memo-table-init-size (access memoize-info-ht-entry v :memo-table-init-size) :aokp (access memoize-info-ht-entry v :aokp) :invoke (access memoize-info-ht-entry v :invoke)) (list (access memoize-info-ht-entry v :record-bytes) (access memoize-info-ht-entry v :record-calls) (access memoize-info-ht-entry v :record-hits) (access memoize-info-ht-entry v :record-mht-calls) (access memoize-info-ht-entry v :record-pons-calls) (access memoize-info-ht-entry v :record-time)))))))
other
(defun-one-output rememoize-all (&optional light) (with-global-memoize-lock (cond (light (let ((new-memoize-info-ht (initial-memoize-info-ht))) (unwind-protect (progn (mf-maphash (lambda (k v) (setf (gethash k new-memoize-info-ht) v)) *memoize-info-ht*) (setq *memoize-info-ht* new-memoize-info-ht)) (when (not (eq *memoize-info-ht* new-memoize-info-ht)) (cond ((eq light :done) (error "Fatal error in rememoize-all!~%Consider evaluating ~ ~s before continuing.~%" '(unmemoize-all))) (t (format t "Error in rememoize-all; about to try again.~%") (rememoize-all :done))))))) (t (let (lst) (mf-maphash (lambda (k v) (declare (ignore v)) (when (symbolp k) (push (memoize-info k) lst))) *memoize-info-ht*) (loop for x in lst do (unmemoize-fn (caar x))) (setq *memoize-info-ht* (initial-memoize-info-ht)) (gc$) (setq *max-symbol-to-fixnum* *initial-max-symbol-to-fixnum*) (loop for x in lst do (progv '(*record-bytes* *record-calls* *record-hits* *record-mht-calls* *record-pons-calls* *record-time*) (cadr x) (apply 'memoize-fn (car x)))))))))
profile-fnfunction
(defun profile-fn (fn &rest r &key (condition nil) (inline nil) &allow-other-keys) (apply (function memoize-fn) fn :condition condition :inline inline r))
other
(defun-one-output profiled-functions nil (with-global-memoize-lock (let (lst) (mf-maphash (lambda (k v) (when (and (symbolp k) (null (access memoize-info-ht-entry v :condition)) (null (access memoize-info-ht-entry v :inline)) (null (access memoize-info-ht-entry v :invoke))) (push k lst))) *memoize-info-ht*) lst)))
other
(defun-one-output unmemoize-profiled
nil
(loop for
x
in
(profiled-functions)
do
(unmemoize-fn (car x))))
other
(defun-one-output coerce-index (x) (cond ((typep x 'fixnum) (assert (and (>= (the fixnum x) 0) (< (the fixnum x) (the fixnum (ash (length *memoize-call-array*) -1))))) x) (t (symbol-to-fixnum x))))
other
(defun-one-output mf-num-to-string (n) (check-type n number) (if (= n 0) (setq n 0)) (cond ((typep n '(integer -99 999)) (format nil "~8d" n)) ((or (< -1000 n -1/100) (< 1/100 n 1000)) (format nil "~8,2f" n)) (t (format nil "~8,2e" n))))
mf-shortenfunction
(defun mf-shorten (x n) (cond ((and (stringp x) (<= (length x) n)) x) (t (let ((x (if (stringp x) (hons-copy x) x))) (cond ((mf-gethash x *mf-shorten-ht*)) (t (let ((*print-pretty* nil) (*print-length* 10) (*print-level* 5) (*print-lines* 2)) (let ((str (with-output-to-string (s) (cond ((stringp x) (princ x s)) (t (prin1 x s)))))) (mf-sethash x (cond ((<= (length str) n) str) (t (concatenate 'string (subseq str 0 (max 0 n)) "///"))) *mf-shorten-ht*)))))))))
other
(defun-one-output mf-print-alist (alist separation) (check-type separation (integer 0)) (setq alist (loop for x in alist collect (progn (check-type x (cons (or string symbol) (cons (or string (integer 0)) null))) (list (mf-shorten (car x) *mf-print-alist-width*) (if (integerp (cadr x)) (mf-num-to-string (cadr x)) (cadr x)))))) (let* ((max1 (loop for x in alist maximize (length (car x)))) (max2 (loop for x in alist maximize (length (cadr x)))) (width (max (or *print-right-margin* *mf-print-right-margin*) (+ separation max1 max2)))) (loop for x in alist do (fresh-line) (princ (car x)) (loop for i below (- width (+ (length (car x)) (length (cadr x)))) do (write-char #\ )) (princ (cadr x)))) nil)
safe-incf-ponsmacro
(defmacro safe-incf-pons (x inc) `(safe-incf ,X ,INC))
other
(defun-one-output pons-summary nil (our-syntax (let ((sssub 0) (nponses 0) (nsubs 0) (nponstab 0)) (declare (type mfixnum sssub nponses nsubs)) (format t "Pons-summary:~%") (with-global-memoize-lock (mf-maphash (lambda (k v) (when (symbolp k) (let ((tab (symbol-value (access memoize-info-ht-entry v :ponstablename)))) (when tab (safe-incf-pons nponstab 1) (mf-maphash (lambda (k v) (declare (ignore k)) (cond ((not (listp v)) (safe-incf-pons sssub (mf-hash-table-size v)) (safe-incf-pons nponses (mf-hash-table-count v)) (safe-incf-pons nsubs 1)) (t (safe-incf-pons nponses (length v))))) tab))))) *memoize-info-ht*)) (mf-print-alist `((" Pons hits/calls" ,(LET* ((C *PONS-CALL-COUNTER*) (M *PONS-MISSES-COUNTER*) (H (- C M))) (FORMAT NIL "~,1e / ~,1e = ~,2f" H C (IF (EQL C 0) 0 (/ H C))))) (" Number of pons tables" ,(MF-NUM-TO-STRING NPONSTAB)) (" Number of pons sub tables" ,(MF-NUM-TO-STRING NSUBS)) (" Sum of pons sub table sizes" ,(MF-NUM-TO-STRING SSSUB)) (" Number of ponses" ,(MF-NUM-TO-STRING NPONSES))) 5) (format t ")") (force-output *standard-output*) nil)))
memoized-valuesfunction
(defun memoized-values (&optional (fn (memoized-functions))) (with-global-memoize-lock (cond ((listp fn) (mapc (function memoized-values) fn)) ((not (memoizedp-raw fn)) (format t "~%; Memoized-values: ~s is not memoized." fn)) (t (let ((tb (symbol-value (access memoize-info-ht-entry (mf-gethash fn *memoize-info-ht*) :tablename)))) (cond ((and tb (not (eql 0 (mf-hash-table-count tb)))) (format t "~%; Memoized values for ~s." fn) (mf-maphash (lambda (key v) (format t "~%~s~%=>~%~s" key v)) tb))))))) (force-output *standard-output*) nil)
print-call-stackfunction
(defun print-call-stack nil (float-ticks/second-init) (our-syntax (let (lst (ticks (internal-real-ticks)) (*print-case* :downcase)) (with-global-memoize-lock (mf-maphash (lambda (k v) (when (symbolp k) (let ((x (symbol-value (the symbol (access memoize-info-ht-entry v :start-ticks))))) (declare (type mfixnum x)) (when (> x 0) (push (cons k x) lst))))) *memoize-info-ht*)) (setq lst (sort lst (function <) :key (function cdr))) (setq lst (loop for pair in lst collect (list (car pair) (mf-num-to-string (/ (the-mfixnum (- ticks (cdr pair))) *float-ticks/second*))))) (when lst (terpri *standard-output*) (mf-print-alist (cons '("Stack of monitored function calls." "Time since outermost call.") lst) 5)))) (force-output *standard-output*) nil)
other
(defun-one-output pons-calls (x) (setq x (coerce-index x)) (aref *memoize-call-array* (ma-index x *ma-pons-index*)))
other
(defun-one-output bytes-allocated (x) (setq x (coerce-index x)) (aref *memoize-call-array* (ma-index x *ma-bytes-index*)))
other
(defun-one-output number-of-hits (x) (setq x (coerce-index x)) (aref *memoize-call-array* (ma-index x *ma-hits-index*)))
other
(defun-one-output number-of-memoized-entries (x) (setq x (coerce-index x)) (with-global-memoize-lock (let ((h (mf-gethash x *memoize-info-ht*))) (unless h (error "~a is not memoized." x)) (let* ((sym (access memoize-info-ht-entry h :tablename)) (val (symbol-value sym))) (if (hash-table-p val) (mf-hash-table-count val) 0)))))
other
(defun-one-output number-of-mht-calls (x) (setq x (coerce-index x)) (aref *memoize-call-array* (ma-index x *ma-mht-index*)))
other
(defun-one-output total-time (x) (setq x (coerce-index x)) (float-ticks/second-init) (/ (aref *memoize-call-array* (ma-index-ticks x)) *float-ticks/second*))
other
(defun-one-output number-of-calls (x) (setq x (coerce-index x)) (aref *memoize-call-array* (ma-index-calls x)))
other
(defun-one-output time-for-non-hits/call (x) (setq x (coerce-index x)) (let ((n (- (number-of-calls x) (number-of-hits x)))) (if (zerop n) 0 (/ (total-time x) n))))
other
(defun-one-output time/call
(x)
(setq x (coerce-index x))
(let ((n (number-of-calls x)))
(if (zerop n)
0
(/ (total-time x) n))))
other
(defun-one-output hits/calls
(x)
(setq x (coerce-index x))
(let ((n (number-of-calls x)))
(if (zerop n)
0
(/ (number-of-hits x) (float n)))))
other
(defun-one-output bytes-allocated/call
(x)
(setq x (coerce-index x))
(let ((n (number-of-calls x)))
(if (zerop n)
0
(/ (bytes-allocated x) n))))
char-list-fractionfunction
(defun char-list-fraction (l) (if (atom l) 0 (+ (char-code (car l)) (/ (char-list-fraction (cdr l)) 256))))
symbol-name-orderfunction
(defun symbol-name-order (s) (unless (symbolp s) (setq s (fixnum-to-symbol s))) (- (char-list-fraction (coerce (symbol-name s) 'list))))
other
(defun-one-output execution-order (s) (unless (symbolp s) (setq s (fixnum-to-symbol s))) (the-mfixnum (symbol-value (the symbol (access memoize-info-ht-entry (mf-gethash s *memoize-info-ht*) :start-ticks)))))
compute-calls-and-timesfunction
(defun compute-calls-and-times nil (with-global-memoize-lock (let ((ma *memoize-call-array*) (2m *2max-memoize-fns*) (ca *callers-array*) (n (the fixnum (1+ *max-symbol-to-fixnum*)))) (declare (type (simple-array mfixnum (*)) ma) (type (simple-array t (*)) ca) (type fixnum 2m n)) (cond ((eql (length ca) n) (loop for i fixnum below n do (setf (aref ca i) nil))) (t (setq *callers-array* (make-array n :initial-element nil)) (setq ca *callers-array*))) (loop for i fixnum below (ma-index-calls n 0 2m) do (setf (aref ma i) 0)) (loop for i fixnum from *initial-max-symbol-to-fixnum* to *max-symbol-to-fixnum* do (let ((col-base (ma-index i 0 2m))) (declare (type mfixnum col-base)) (loop for j fixnum from *initial-max-symbol-to-fixnum* to *max-symbol-to-fixnum* do (let* ((calls-row (ma-index-calls j)) (index (ma-index-from-col-base col-base calls-row)) (calls (the-mfixnum (aref ma index)))) (declare (type mfixnum calls-row index calls)) (when (> calls 0) (let* ((ticks-index (the-mfixnum (1+ index))) (ticks (aref ma ticks-index)) (ticks-row (the-mfixnum (1+ calls-row)))) (declare (type mfixnum ticks-index ticks ticks-row)) (safe-incf (aref ma calls-row) calls compute-calls-and-times) (safe-incf (aref ma ticks-row) ticks compute-calls-and-times) (push i (aref ca j)))))))))))
other
(defun-one-output print-not-called nil (with-global-memoize-lock (compute-calls-and-times) (let ((ans nil)) (mf-maphash (lambda (k v) (declare (ignore v)) (when (and (symbolp k) (eql 0 (number-of-calls k))) (push k ans))) *memoize-info-ht*) (loop for x in (sort ans 'alphorder) do (print x)))))
other
(defun-one-output memoize-summary-sort
nil
(labels ((lex-> (l1 l2)
(cond ((or (atom l1) (atom l2)) nil)
((> (car l1) (car l2)) t)
((< (car l1) (car l2)) nil)
(t (lex-> (cdr l1) (cdr l2))))))
(let (pairs)
(with-global-memoize-lock (mf-maphash (lambda (fn v)
(when (symbolp fn)
(let ((num (access memoize-info-ht-entry v :num)))
(declare (type mfixnum num))
(when (< 0 (number-of-calls num))
(push (cons fn
(loop for
order
in
*memoize-summary-order-list*
collect
(funcall order fn)))
pairs)))))
*memoize-info-ht*)
(sort pairs
(if *memoize-summary-order-reversed*
(lambda (x y) (lex-> y x))
(function lex->))
:key (function cdr))))))
other
(defun-one-output outside-caller-p (x) (with-global-memoize-lock (or (<= x *initial-max-symbol-to-fixnum*) (null (mf-gethash x *memoize-info-ht*)))))
other
(defun-one-output memoize-condition (fn) (with-global-memoize-lock (let ((x (mf-gethash fn *memoize-info-ht*))) (and x (access memoize-info-ht-entry x :condition)))))
other
(defun-one-output memoize-summary-after-compute-calls-and-times nil (with-global-memoize-lock (float-ticks/second-init) (our-syntax (let* ((fn-pairs (memoize-summary-sort)) (ma *memoize-call-array*) (len-orig-fn-pairs (len fn-pairs)) (len-fn-pairs 0) (global-bytes-allocated 0) (global-pons-calls 0)) (declare (type (simple-array mfixnum (*)) ma) (type fixnum len-orig-fn-pairs len-fn-pairs)) (when (and *memoize-summary-limit* (> len-orig-fn-pairs *memoize-summary-limit*)) (setq fn-pairs (take *memoize-summary-limit* fn-pairs))) (setq len-fn-pairs (len fn-pairs)) (when (> len-fn-pairs 0) (format t "~%Sorted by *memoize-summary-order-list* = ~s." *memoize-summary-order-list*) (when (< len-fn-pairs len-orig-fn-pairs) (format t "~%Reporting on ~:d of ~:d functions because ~ *memoize-summary-limit* = ~a." len-fn-pairs len-orig-fn-pairs *memoize-summary-limit*))) (setq global-bytes-allocated (loop for pair in fn-pairs sum (bytes-allocated (car pair)))) (setq global-pons-calls (loop for pair in fn-pairs sum (pons-calls (car pair)))) (when (null fn-pairs) (format t "~%(memoize-summary) has nothing to report.~%")) (loop for pair in fn-pairs do (let* ((fn (car pair)) (entry (mf-gethash fn *memoize-info-ht*)) (tablename (symbol-value (access memoize-info-ht-entry entry :tablename))) (ponstablename (symbol-value (access memoize-info-ht-entry entry :ponstablename))) (start-ticks (the-mfixnum (symbol-value (the symbol (access memoize-info-ht-entry entry :start-ticks))))) (num (the-mfixnum (access memoize-info-ht-entry entry :num))) (nhits (the-mfixnum (number-of-hits num))) (nmht (the-mfixnum (number-of-mht-calls num))) (ncalls (the-mfixnum (number-of-calls num))) (pons-calls (the-mfixnum (pons-calls num))) (no-hits (or (not *report-hits*) (null (memoize-condition fn)))) (bytes-allocated (bytes-allocated num)) (tt (max 1.0e-6 (total-time num))) (t/c (time/call num)) (in-progress-str (if (eql start-ticks -1) "" " (running)")) (selftime tt)) (declare (type integer start-ticks) (type mfixnum num nhits nmht ncalls pons-calls bytes-allocated)) (format t "~%(~s~%" fn) (mf-print-alist `(,@(WHEN (OR *REPORT-CALLS* *REPORT-HITS*) `((,(FORMAT NIL " ~a~a" (IF NO-HITS "Calls" "Hits/calls") IN-PROGRESS-STR) ,(COND (NO-HITS (FORMAT NIL "~a" (MF-NUM-TO-STRING NCALLS))) ((ZEROP NCALLS) (FORMAT NIL "~8,2e/~8,2e = ????%" NHITS 0)) (T (FORMAT NIL "~8,2e/~8,2e = ~4,1f%" NHITS NCALLS (* 100 (/ NHITS (FLOAT NCALLS))))))))) ,@(WHEN (AND *REPORT-MHT-CALLS* (>= NMHT 2)) `((" Number of calls to mht" ,(MF-NUM-TO-STRING NMHT)))) ,@(WHEN *REPORT-TIME* `((" Time of all outermost calls" ,(FORMAT NIL "~a" (MF-NUM-TO-STRING TT))) (" Time per call" ,(MF-NUM-TO-STRING T/C)))) ,@(WHEN (AND (> BYTES-ALLOCATED 0) *REPORT-BYTES*) (ASSERT (> GLOBAL-BYTES-ALLOCATED 0)) `((" Heap bytes allocated" ,(FORMAT NIL "~a; ~4,1f%" (MF-NUM-TO-STRING BYTES-ALLOCATED) (* 100 (/ BYTES-ALLOCATED GLOBAL-BYTES-ALLOCATED)))) (" Heap bytes allocated per call" ,(MF-NUM-TO-STRING (/ BYTES-ALLOCATED NCALLS))))) ,@(WHEN (AND (> PONS-CALLS 0) *REPORT-PONS-CALLS*) (ASSERT (> GLOBAL-PONS-CALLS 0)) `((" Pons calls" ,(FORMAT NIL "~a; ~4,1f%" (MF-NUM-TO-STRING PONS-CALLS) (* 100 (/ PONS-CALLS GLOBAL-PONS-CALLS)))))) ,@(WHEN (AND *REPORT-HITS* *REPORT-TIME* (NOT (EQL 0 NHITS))) `((" Time per missed call" ,(MF-NUM-TO-STRING (TIME-FOR-NON-HITS/CALL NUM))))) ,@(WHEN *REPORT-CALLS-TO* (LET ((LST NIL) (OUTSIDE-FN-TIME 0) (OUTSIDE-FN-COUNT 0)) (DECLARE (TYPE MFIXNUM OUTSIDE-FN-COUNT)) (LOOP FOR CALLERN IN (LOOP FOR I BELOW (LENGTH *CALLERS-ARRAY*) WHEN (MEMBER NUM (AREF *CALLERS-ARRAY* I)) COLLECT I) DO (LET* ((CALL-LOC (MA-INDEX-CALLS CALLERN NUM)) (CALLS (AREF MA CALL-LOC)) (TICKS-LOC (THE-MFIXNUM (1+ CALL-LOC))) (TICKS (AREF MA TICKS-LOC)) (LOCAL-TT (/ TICKS *FLOAT-TICKS/SECOND*))) (DECLARE (TYPE MFIXNUM CALL-LOC CALLS TICKS-LOC TICKS)) (DECF SELFTIME LOCAL-TT) (COND ((OR (OUTSIDE-CALLER-P CALLERN) (< (* 100 LOCAL-TT) TT)) (INCF OUTSIDE-FN-TIME LOCAL-TT) (SAFE-INCF OUTSIDE-FN-COUNT CALLS MEMOIZE-SUMMARY-AFTER-COMPUTE-CALLS-AND-TIMES)) (T (PUSH `((,(FORMAT NIL " To ~s" (FIXNUM-TO-SYMBOL CALLERN)) ,(FORMAT NIL "~8,2e calls took~8,2e; ~a%" CALLS LOCAL-TT (COND ((> (* 10000 LOCAL-TT) TT) (ASSERT (< 0 TT)) (FORMAT NIL "~4,1f" (* 100 (/ LOCAL-TT TT)))) (T "<0.01")))) . ,(IF *SORT-TO-FROM-BY-CALLS* CALLS LOCAL-TT)) LST))))) (WHEN (> OUTSIDE-FN-TIME 0) (ASSERT (< 0 TT)) (PUSH `((,(FORMAT NIL " To other functions") ,(FORMAT NIL "~8,2e calls took~8,2e; ~a%" OUTSIDE-FN-COUNT OUTSIDE-FN-TIME (IF (> (* 10000 OUTSIDE-FN-TIME) TT) (FORMAT NIL "~4,1f" (* 100 (/ OUTSIDE-FN-TIME TT))) "<0.01"))) . ,(IF *SORT-TO-FROM-BY-CALLS* OUTSIDE-FN-COUNT OUTSIDE-FN-TIME)) LST)) (WHEN (AND (> SELFTIME 0) (NOT (= SELFTIME TT))) (ASSERT (< 0 TT)) (PUSH `((" To self/unprofiled functions" ,(FORMAT NIL "~8,2e; ~a%" SELFTIME (IF (> (* 10000 SELFTIME) TT) (FORMAT NIL "~4,1f" (* 100 (/ SELFTIME TT))) "<0.01"))) . ,(IF *SORT-TO-FROM-BY-CALLS* 0 SELFTIME)) LST)) (SETQ LST (SORT LST #'> :KEY #'CDR)) (STRIP-CARS LST))) ,@(WHEN *REPORT-CALLS-FROM* (LET ((LST NIL) (OUTSIDE-CALLER-TIME 0) (OUTSIDE-CALLER-COUNT 0)) (LOOP FOR CALLERN IN (AREF *CALLERS-ARRAY* NUM) DO (LET* ((CALL-LOC (MA-INDEX-CALLS NUM CALLERN)) (CALLS (AREF MA CALL-LOC)) (TICKS-LOC (THE-MFIXNUM (1+ CALL-LOC))) (TICKS (AREF MA TICKS-LOC)) (LOCAL-TT (/ TICKS *FLOAT-TICKS/SECOND*))) (DECLARE (TYPE MFIXNUM CALL-LOC CALLS TICKS-LOC TICKS)) (COND ((OR (OUTSIDE-CALLER-P CALLERN) (< (* 100 LOCAL-TT) TT)) (INCF OUTSIDE-CALLER-TIME LOCAL-TT) (INCF OUTSIDE-CALLER-COUNT CALLS)) (T (PUSH `((,(FORMAT NIL " From ~s" (FIXNUM-TO-SYMBOL CALLERN)) ,(FORMAT NIL "~8,2e calls took~8,2e; ~a%" CALLS LOCAL-TT (IF (AND (<= 0.001 LOCAL-TT) (<= LOCAL-TT TT)) (FORMAT NIL "~4,1f" (* 100 (/ LOCAL-TT TT))) "?"))) . ,(IF *SORT-TO-FROM-BY-CALLS* CALLS LOCAL-TT)) LST))))) (WHEN (> OUTSIDE-CALLER-TIME 0) (PUSH `((,(FORMAT NIL " From other functions") ,(FORMAT NIL "~8,2e calls took~8,2e; ~a%" OUTSIDE-CALLER-COUNT OUTSIDE-CALLER-TIME (IF (AND (<= 0.001 OUTSIDE-CALLER-TIME) (<= OUTSIDE-CALLER-TIME TT)) (FORMAT NIL "~4,1f" (* 100 (/ OUTSIDE-CALLER-TIME TT))) "?"))) . ,(IF *SORT-TO-FROM-BY-CALLS* OUTSIDE-CALLER-COUNT OUTSIDE-CALLER-TIME)) LST)) (SETQ LST (SORT LST #'> :KEY #'CDR)) (STRIP-CARS LST))) ,@(WHEN (OR *REPORT-ON-MEMO-TABLES* *REPORT-ON-PONS-TABLES*) (LET ((SUM-PONS-SUB-SIZES 0) (NPONSES 0) (NPONSSUBS 0)) (DECLARE (TYPE MFIXNUM SUM-PONS-SUB-SIZES NPONSES NPONSSUBS)) (AND PONSTABLENAME *REPORT-ON-PONS-TABLES* (MF-MAPHASH (LAMBDA (KEY VALUE) (DECLARE (IGNORE KEY)) (COND ((NOT (LISTP VALUE)) (SAFE-INCF-PONS SUM-PONS-SUB-SIZES (MF-HASH-TABLE-SIZE VALUE)) (SAFE-INCF-PONS NPONSES (MF-HASH-TABLE-COUNT VALUE)) (SAFE-INCF-PONS NPONSSUBS 1)) (T (SAFE-INCF-PONS NPONSES (LENGTH VALUE))))) PONSTABLENAME)) `(,@(AND TABLENAME *REPORT-ON-MEMO-TABLES* (LET ((COUNT (MF-HASH-TABLE-COUNT TABLENAME)) (SIZE (MF-HASH-TABLE-SIZE TABLENAME))) `((,(FORMAT NIL " Memoize table count/size") ,(FORMAT NIL "~8,2e/~8,2e = ~4,1f%" COUNT SIZE (* 100 (/ COUNT SIZE))))))) ,@(AND PONSTABLENAME *REPORT-ON-PONS-TABLES* (LET ((COUNT (MF-HASH-TABLE-COUNT PONSTABLENAME)) (SIZE (MF-HASH-TABLE-SIZE PONSTABLENAME))) `((" (Pons table count/size" ,(FORMAT NIL "~:d/~:d = ~4,1f%)" COUNT SIZE (* 100 (/ COUNT SIZE)))) (" (Number of pons sub tables" ,(FORMAT NIL "~a)" (MF-NUM-TO-STRING NPONSSUBS))) (" (Sum of pons sub table sizes" ,(FORMAT NIL "~a)" (MF-NUM-TO-STRING SUM-PONS-SUB-SIZES))) (" (Number of ponses" ,(FORMAT NIL "~a)" (MF-NUM-TO-STRING NPONSES)))))))))) 5)) (format t ")")))) (terpri *standard-output*) (force-output *standard-output*)) nil)
other
(defun-one-output memoize-summary nil (compute-calls-and-times) (memoize-summary-after-compute-calls-and-times) nil)
clear-one-memo-and-pons-hashfunction
(defun clear-one-memo-and-pons-hash (l strategy) (with-global-memoize-lock (let* ((fn (access memoize-info-ht-entry l :fn)) (mt (symbol-value (access memoize-info-ht-entry l :tablename))) (pt (symbol-value (access memoize-info-ht-entry l :ponstablename))) (mt-count (and mt (mf-hash-table-count mt))) (pt-count (and pt (mf-hash-table-count pt)))) (when mt (let* ((mt-target-size (memoize-table-desired-size fn 0))) (if (or (eq strategy :clear) (and (eq strategy :auto) (< mt-count mt-target-size))) (unless (eql 0 mt-count) (clrhash mt)) (setf (symbol-value (access memoize-info-ht-entry l :tablename)) nil)))) (when pt (let* ((pt-target-size (pons-table-desired-size fn 0))) (if (or (eq strategy :clear) (and (eq strategy :auto) (< pt-count pt-target-size))) (unless (eql 0 pt-count) (clrhash pt)) (setf (symbol-value (access memoize-info-ht-entry l :ponstablename)) nil)))) (when (or mt-count pt-count) (update-memo-max-sizes fn (or pt-count 1) (or mt-count 1))))) nil)
other
(defun-one-output clear-memoize-table (k) (with-global-memoize-lock (when (symbolp k) (let ((l (mf-gethash k *memoize-info-ht*))) (when l (clear-one-memo-and-pons-hash l :auto))))) k)
other
(defun-one-output clear-memoize-tables nil (with-global-memoize-lock (let (success) (unwind-protect (progn (mf-maphash (lambda (k l) (when (symbolp k) (clear-one-memo-and-pons-hash l :null))) *memoize-info-ht*) (setq success t)) (or success (error "clear-memoize-tables failed.")))) (setq *pons-call-counter* 0) (setq *pons-misses-counter* 0)) nil)
clear-memoize-call-arrayfunction
(defun clear-memoize-call-array nil (with-global-memoize-lock (let ((ma *memoize-call-array*)) (declare (type (simple-array mfixnum (*)) ma)) (let ((len (length ma))) (cond ((typep len 'fixnum) (loop for i fixnum below len do (setf (aref ma i) 0))) (t (loop for i of-type integer below len do (setf (aref ma i) 0))))))))
clear-memoize-statisticsfunction
(defun clear-memoize-statistics nil (with-global-memoize-lock (setq *pons-call-counter* 0) (setq *pons-misses-counter* 0) (clear-memoize-call-array)) nil)
other
(defun-one-output memoize-init nil (with-global-memoize-lock (when *memoize-init-done* (return-from memoize-init nil)) (unless (eql *caller* (the-mfixnum (outside-caller-col-base))) (error "memoize-init: A memoized function is running.")) (let (success) (unwind-protect (progn (setq *pons-call-counter* 0) (setq *pons-misses-counter* 0) (setq *memoize-info-ht* (initial-memoize-info-ht)) (mf-sethash *initial-max-symbol-to-fixnum* "outside-caller" *memoize-info-ht*) (setq *max-symbol-to-fixnum* *initial-max-symbol-to-fixnum*) (setq *2max-memoize-fns* *initial-2max-memoize-fns*) (sync-memoize-call-array) (setq *memo-max-sizes* (mf-mht :shared :default)) (setq success t)) (if success (setq *memoize-init-done* t) (error "memoize-init failed."))))) nil)
with-lower-overheadmacro
(defmacro with-lower-overhead (&rest r) `(let ((*record-bytes* nil) (*record-calls* nil) (*record-hits* nil) (*record-mht-calls* nil) (*record-pons-calls* nil) (*record-time* nil)) ,@R))
with-higher-overheadmacro
(defmacro with-higher-overhead (&rest r) `(let ((*record-bytes* t) (*record-calls* t) (*record-hits* t) (*record-mht-calls* t) (*record-pons-calls* t) (*record-time* t)) ,@R))
with-overheadmacro
(defmacro with-overhead (val form) (let ((v (gensym))) `(let ((,V ,VAL)) (cond ((eq ,V :default) ,FORM) ((null ,V) (with-lower-overhead ,FORM)) (t (with-higher-overhead ,FORM))))))
acl2h-init-memoizationsfunction
(defun acl2h-init-memoizations nil (loop for entry in *thread-unsafe-builtin-memoizations* when (not (memoizedp-raw (car entry))) do (with-lower-overhead (apply 'memoize-fn entry))))
set-bad-lisp-consp-memoizefunction
(defun set-bad-lisp-consp-memoize (arg) (cond (arg (when (not (memoizedp-raw 'bad-lisp-consp)) (with-lower-overhead (apply 'memoize-fn *bad-lisp-consp-memoization*)))) (t (when (memoizedp-raw 'bad-lisp-consp) (unmemoize-fn 'bad-lisp-consp)))))
other
(defun-one-output acl2h-init nil nil)
memstatfunction
(defun memstat (&rest r) (apply (function memoized-values) r))
clear-memo-tablesfunction
(defun clear-memo-tables nil (clear-memoize-tables))
lower-overheadfunction
(defun lower-overhead nil (setq *record-bytes* nil) (setq *record-calls* nil) (setq *record-hits* nil) (setq *record-mht-calls* nil) (setq *record-pons-calls* nil) (setq *record-time* nil))
update-memo-entry-for-attachmentsfunction
(defun update-memo-entry-for-attachments (fns entry special-name wrld) (let* ((ext-anc-attachments (access memoize-info-ht-entry entry :ext-anc-attachments)) (valid-p (if (eq fns :clear) :clear (or (null ext-anc-attachments) (ext-anc-attachments-valid-p fns ext-anc-attachments special-name wrld t))))) (cond ((eq valid-p t) (mv nil entry)) (t (mv (if (eq valid-p nil) t valid-p) (change memoize-info-ht-entry entry :ext-anc-attachments (ext-ancestors-attachments (access memoize-info-ht-entry entry :fn) wrld)))))))
update-memo-entries-for-attachmentsfunction
(defun update-memo-entries-for-attachments (fns wrld state) (let ((ctx 'top-level) (fns (if (eq fns :clear) :clear (strict-merge-sort-symbol< (loop for fn in fns collect (canonical-sibling fn wrld))))) (special-name *special-cltl-cmd-attachment-mark-name*)) (when (eq fns :clear) (observation ctx "Memoization tables for functions memoized with :AOKP T ~ are being cleared.")) (when fns (with-global-memoize-lock (mf-maphash (lambda (k entry) (when (symbolp k) (mv-let (changedp new-entry) (update-memo-entry-for-attachments fns entry special-name wrld) (when changedp (when (not (or (eq changedp t) (eq fns :clear))) (observation ctx "Memoization table for function ~x0 is ~ being cleared because ~@1." k (if (eq changedp special-name) "it depends on apply$-userfn or ~ badge-userfn and at least one badge ~ has changed" (msg "the attachment to function ~x0 ~ has changed" changedp))) (clear-one-memo-and-pons-hash entry :auto)) (mf-sethash k new-entry *memoize-info-ht*))))) *memoize-info-ht*)))) (clear-memoize-table 'canonical-ancestors-rec) (clear-memoize-table 'immediate-canonical-ancestors) (clear-memoize-table 'canonical-ancestors-tr-rec) (clear-memoize-table 'immediate-canonical-ancestors-tr) (clear-memoize-table 'canonical-ancestors-path) (clear-memoize-table 'canonical-ancestors-tr-path))