X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fpcl%2Fdlisp.lisp;h=486541b1c79b196af6d8940168c3dfba5379c8ab;hb=562e48a2bd3467121e24214110e535c841fbb622;hp=516982d6c6bc2877c1ad647ffe71fc85b85aa192;hpb=9a133510326a9d9f95ecd99af8fecfcbedeba65c;p=sbcl.git diff --git a/src/pcl/dlisp.lisp b/src/pcl/dlisp.lisp index 516982d..486541b 100644 --- a/src/pcl/dlisp.lisp +++ b/src/pcl/dlisp.lisp @@ -23,6 +23,7 @@ (in-package "SB-PCL") + ;;;; some support stuff for getting a hold of symbols that we need when ;;;; building the discriminator codes. It's OK for these to be interned ;;;; symbols because we don't capture any user code in the scope in which @@ -43,17 +44,14 @@ (format-symbol *pcl-package* ".SLOTS~A." arg-number))) (declaim (inline make-dfun-required-args)) -(defun make-dfun-required-args (metatypes) - ;; Micro-optimizations 'R Us - (labels ((rec (types i) - (declare (fixnum i)) - (when types - (cons (dfun-arg-symbol i) - (rec (cdr types) (1+ i)))))) - (rec metatypes 0))) - -(defun make-dfun-lambda-list (metatypes applyp) - (let ((required (make-dfun-required-args metatypes))) +(defun make-dfun-required-args (count) + (declare (type index count)) + (let (result) + (dotimes (i count (nreverse result)) + (push (dfun-arg-symbol i) result)))) + +(defun make-dfun-lambda-list (nargs applyp) + (let ((required (make-dfun-required-args nargs))) (if applyp (nconc required ;; Use &MORE arguments to avoid consing up an &REST list @@ -61,10 +59,10 @@ ;; INVOKE-EFFECTIVE-METHOD-FUNCTION for the other ;; pieces. '(&more .dfun-more-context. .dfun-more-count.)) - required))) + required))) -(defun make-dlap-lambda-list (metatypes applyp) - (let* ((required (make-dfun-required-args metatypes)) +(defun make-dlap-lambda-list (nargs applyp) + (let* ((required (make-dfun-required-args nargs)) (lambda-list (if applyp (append required '(&more .more-context. .more-count.)) required))) @@ -81,8 +79,8 @@ (when applyp '(.more-context. .more-count.))))) -(defun make-emf-call (metatypes applyp fn-variable &optional emf-type) - (let ((required (make-dfun-required-args metatypes))) +(defun make-emf-call (nargs applyp fn-variable &optional emf-type) + (let ((required (make-dfun-required-args nargs))) `(,(if (eq emf-type 'fast-method-call) 'invoke-effective-method-function-fast 'invoke-effective-method-function) @@ -102,9 +100,8 @@ :more-arg ,(when applyp '(.dfun-more-context. .dfun-more-count.))))) -(defun make-fast-method-call-lambda-list (metatypes applyp) - (list* '.pv-cell. '.next-method-call. - (make-dfun-lambda-list metatypes applyp))) +(defun make-fast-method-call-lambda-list (nargs applyp) + (list* '.pv-cell. '.next-method-call. (make-dfun-lambda-list nargs applyp))) ;;; Emitting various accessors. @@ -184,7 +181,7 @@ (return-from emit-default-only (emit-default-only-function metatypes applyp)))) (multiple-value-bind (lambda-list args rest-arg more-arg) - (make-dlap-lambda-list metatypes applyp) + (make-dlap-lambda-list (length metatypes) applyp) (generating-lisp '(emf) lambda-list `(invoke-effective-method-function emf @@ -224,9 +221,7 @@ (let ((instance nil) (arglist ()) (closure-variables ()) - (field +first-wrapper-cache-number-index+) (read-form (emit-slot-read-form class-slot-p 'index 'slots))) - ;;we need some field to do the fast obsolete check (ecase reader/writer ((:reader :boundp) (setq instance (dfun-arg-symbol 0) @@ -252,7 +247,7 @@ (fsc-instance-wrapper ,instance))))) (block access (when (and wrapper - (/= (layout-clos-hash wrapper ,field) 0) + (not (zerop (layout-clos-hash wrapper))) ,@(if (eql 1 1-or-2-class) `((eq wrapper wrapper-0)) `((or (eq wrapper wrapper-0) @@ -264,7 +259,7 @@ (return-from access value))))) (:boundp `((let ((value ,read-form)) - (return-from access (not (eq value +slot-unbound+)))))) + (return-from access (not (eq value +slot-unbound+)))))) (:writer `((return-from access (setf ,read-form ,(car arglist))))))) (funcall miss-fn ,@arglist)))))) @@ -314,7 +309,7 @@ arglist `(let (,@(unless class-slot-p '(slots)) ,@(when cached-index-p '(index))) - ,(emit-dlap arglist metatypes + ,(emit-dlap 'cache arglist metatypes (emit-slot-access reader/writer class-slot-p 'slots 'index 'miss-fn arglist) `(funcall miss-fn ,@arglist) @@ -345,13 +340,12 @@ (emit-checking-or-caching-function cached-emf-p return-value-p metatypes applyp)))) (multiple-value-bind (lambda-list args rest-arg more-arg) - (make-dlap-lambda-list metatypes applyp) + (make-dlap-lambda-list (length metatypes) applyp) (generating-lisp `(cache ,@(unless cached-emf-p '(emf)) miss-fn) lambda-list `(let (,@(when cached-emf-p '(emf))) - ,(emit-dlap args - metatypes + ,(emit-dlap 'cache args metatypes (if return-value-p (if cached-emf-p 'emf t) `(invoke-effective-method-function @@ -371,8 +365,10 @@ (values (emit-checking-or-caching cached-emf-p return-value-p metatypes applyp)))) -(defun emit-dlap (args metatypes hit miss value-reg &optional slot-regs) +(defun emit-dlap (cache-var args metatypes hit-form miss-form value-var + &optional slot-vars) (let* ((index -1) + (miss-tag (gensym "MISSED")) (wrapper-bindings (mapcan (lambda (arg mt) (unless (eq mt t) (incf index) @@ -380,151 +376,19 @@ "WRAPPER-~D" index) ,(emit-fetch-wrapper - mt arg 'miss (pop slot-regs)))))) + mt arg miss-tag (pop slot-vars)))))) args metatypes)) - (wrappers (mapcar #'car wrapper-bindings))) + (wrapper-vars (mapcar #'car wrapper-bindings))) (declare (fixnum index)) - (unless wrappers (error "Every metatype is T.")) - `(block dfun - (tagbody - (let ((field (cache-field cache)) - (cache-vector (cache-vector cache)) - (mask (cache-mask cache)) - (size (cache-size cache)) - (overflow (cache-overflow cache)) - ,@wrapper-bindings) - (declare (fixnum size field mask)) - ,(cond ((cdr wrappers) - (emit-greater-than-1-dlap wrappers 'miss value-reg)) - (value-reg - (emit-1-t-dlap (car wrappers) 'miss value-reg)) - (t - (emit-1-nil-dlap (car wrappers) 'miss))) - (return-from dfun ,hit)) - miss - (return-from dfun ,miss))))) - -(defun emit-1-nil-dlap (wrapper miss-label) - `(let* ((primary ,(emit-1-wrapper-compute-primary-cache-location wrapper - miss-label)) - (location primary)) - (declare (fixnum primary location)) - (block search - (loop (when (eq ,wrapper (cache-vector-ref cache-vector location)) - (return-from search nil)) - (setq location (the fixnum (+ location 1))) - (when (= location size) - (setq location 0)) - (when (= location primary) - (dolist (entry overflow) - (when (eq (car entry) ,wrapper) - (return-from search nil))) - (go ,miss-label)))))) - -(defmacro get-cache-vector-lock-count (cache-vector) - `(let ((lock-count (cache-vector-lock-count ,cache-vector))) - (unless (typep lock-count 'fixnum) - (error "My cache got freed somehow.")) - (the fixnum lock-count))) - -(defun emit-1-t-dlap (wrapper miss-label value) - `(let ((primary ,(emit-1-wrapper-compute-primary-cache-location wrapper - miss-label)) - (initial-lock-count (get-cache-vector-lock-count cache-vector))) - (declare (fixnum primary initial-lock-count)) - (let ((location primary)) - (declare (fixnum location)) - (block search - (loop (when (eq ,wrapper (cache-vector-ref cache-vector location)) - (setq ,value (cache-vector-ref cache-vector (1+ location))) - (return-from search nil)) - (setq location (the fixnum (+ location 2))) - (when (= location size) - (setq location 0)) - (when (= location primary) - (dolist (entry overflow) - (when (eq (car entry) ,wrapper) - (setq ,value (cdr entry)) - (return-from search nil))) - (go ,miss-label)))) - (unless (= initial-lock-count - (get-cache-vector-lock-count cache-vector)) - (go ,miss-label))))) - -(defun emit-greater-than-1-dlap (wrappers miss-label value) - (declare (type list wrappers)) - (let ((cache-line-size (compute-line-size (+ (length wrappers) - (if value 1 0))))) - `(let ((primary 0) - (size-1 (the fixnum (- size 1)))) - (declare (fixnum primary size-1)) - ,(emit-n-wrapper-compute-primary-cache-location wrappers miss-label) - (let ((initial-lock-count (get-cache-vector-lock-count cache-vector))) - (declare (fixnum initial-lock-count)) - (let ((location primary) - (next-location 0)) - (declare (fixnum location next-location)) - (block search - (loop (setq next-location - (the fixnum (+ location ,cache-line-size))) - (when (and ,@(mapcar - (lambda (wrapper) - `(eq ,wrapper - (cache-vector-ref - cache-vector - (setq location - (the fixnum (+ location 1)))))) - wrappers)) - ,@(when value - `((setq location (the fixnum (+ location 1))) - (setq ,value (cache-vector-ref cache-vector - location)))) - (return-from search nil)) - (setq location next-location) - (when (= location size-1) - (setq location 0)) - (when (= location primary) - (dolist (entry overflow) - (let ((entry-wrappers (car entry))) - (when (and ,@(mapcar (lambda (wrapper) - `(eq ,wrapper - (pop entry-wrappers))) - wrappers)) - ,@(when value - `((setq ,value (cdr entry)))) - (return-from search nil)))) - (go ,miss-label)))) - (unless (= initial-lock-count - (get-cache-vector-lock-count cache-vector)) - (go ,miss-label))))))) - -(defun emit-1-wrapper-compute-primary-cache-location (wrapper miss-label) - `(let ((wrapper-cache-no (layout-clos-hash ,wrapper field))) - (declare (fixnum wrapper-cache-no)) - (when (zerop wrapper-cache-no) (go ,miss-label)) - ,(let ((form `(logand mask wrapper-cache-no))) - `(the fixnum ,form)))) - -(defun emit-n-wrapper-compute-primary-cache-location (wrappers miss-label) - (declare (type list wrappers)) - ;; This returns 1 less that the actual location. - `(progn - ,@(let ((adds 0) (len (length wrappers))) - (declare (fixnum adds len)) - (mapcar (lambda (wrapper) - `(let ((wrapper-cache-no (layout-clos-hash ,wrapper field))) - (declare (fixnum wrapper-cache-no)) - (when (zerop wrapper-cache-no) (go ,miss-label)) - (setq primary (the fixnum (+ primary wrapper-cache-no))) - ,@(progn - (incf adds) - (when (or (zerop (mod adds - wrapper-cache-number-adds-ok)) - (eql adds len)) - `((setq primary - ,(let ((form `(logand primary mask))) - `(the fixnum ,form)))))))) - wrappers)))) + (unless wrapper-vars + (error "Every metatype is T.")) + `(prog () + (return + (let ,wrapper-bindings + ,(emit-cache-lookup cache-var wrapper-vars miss-tag value-var) + ,hit-form)) + ,miss-tag + (return ,miss-form)))) ;;; CMU17 (and SBCL) note: Since STD-INSTANCE-P is weakened in the ;;; CMU/SBCL approach of using funcallable instances, that branch may @@ -533,7 +397,7 @@ ;;; "slots" will be whatever the first slot is, but will be ignored. ;;; Similarly, FSC-INSTANCE-P returns true on funcallable structures ;;; as well as PCL fins. -(defun emit-fetch-wrapper (metatype argument miss-label &optional slot) +(defun emit-fetch-wrapper (metatype argument miss-tag &optional slot) (ecase metatype ((standard-instance) `(cond ((std-instance-p ,argument) @@ -543,11 +407,19 @@ ,@(when slot `((setq ,slot (fsc-instance-slots ,argument)))) (fsc-instance-wrapper ,argument)) (t - (go ,miss-label)))) - (class + (go ,miss-tag)))) + ;; Sep92 PCL used to distinguish between some of these cases (and + ;; spuriously exclude others). Since in SBCL + ;; WRAPPER-OF/LAYOUT-OF/BUILT-IN-OR-STRUCTURE-WRAPPER are all + ;; equivalent and inlined to each other, we can collapse some + ;; spurious differences. + ((class built-in-instance structure-instance condition-instance) (when slot (error "can't do a slot reg for this metatype")) `(wrapper-of ,argument)) - ((built-in-instance structure-instance) - (when slot (error "can't do a slot reg for this metatype")) - `(built-in-or-structure-wrapper - ,argument)))) + ;; a metatype of NIL should never be seen here, as NIL is only in + ;; the metatypes before a generic function is fully initialized. + ;; T should never be seen because we never need to get a wrapper + ;; to do dispatch if all methods have T as the respective + ;; specializer. + ((t nil) + (bug "~@" metatype 'emit-fetch-wrapper))))