X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fpcl%2Flow.lisp;h=a8e412224c4d6bfc2c9b70dded0dfa202203cf1b;hb=d7cbe5c40e93796d326937f3fb962fa4d7b1fa85;hp=aa65f9ef8b27e37cc3d5fac2255b0f445ceb994d;hpb=832f3b5652ae1b4a8888829cd4a1b391a8ca9952;p=sbcl.git diff --git a/src/pcl/low.lisp b/src/pcl/low.lisp index aa65f9e..a8e4122 100644 --- a/src/pcl/low.lisp +++ b/src/pcl/low.lisp @@ -39,13 +39,32 @@ (eval-when (:compile-toplevel :load-toplevel :execute) (defvar *optimize-speed* - '(optimize (speed 3) (safety 0))) + '(optimize (speed 3) (safety 0) (sb-ext:inhibit-warnings 3))) ) ; EVAL-WHEN (defmacro dotimes-fixnum ((var count &optional (result nil)) &body body) `(dotimes (,var (the fixnum ,count) ,result) (declare (fixnum ,var)) ,@body)) + +(declaim (inline random-fixnum)) +(defun random-fixnum () + (random (1+ most-positive-fixnum))) + +;;; Lambda which executes its body (or not) randomly. Used to drop +;;; random cache entries. +(defmacro randomly-punting-lambda (lambda-list &body body) + (with-unique-names (drops drop-pos) + `(let ((,drops (random-fixnum)) + (,drop-pos sb-vm:n-fixnum-bits)) + (declare (fixnum ,drops) + (type (integer 0 #.sb-vm:n-fixnum-bits) ,drop-pos)) + (lambda ,lambda-list + (when (logbitp (the unsigned-byte (decf ,drop-pos)) ,drops) + (locally ,@body)) + (when (zerop ,drop-pos) + (setf ,drops (random-fixnum) + ,drop-pos sb-vm:n-fixnum-bits)))))) ;;;; early definition of WRAPPER ;;;; @@ -66,12 +85,12 @@ ;; default of WRAPPER-INVALID. Instead of trying ;; to find out, I just overrode the LAYOUT ;; default here. -- WHN 19991204 - (invalid nil)) - (:conc-name %wrapper-) + (invalid nil) + ;; This allows quick testing of wrapperness. + (for-std-class-p t)) (:constructor make-wrapper-internal) (:copier nil)) - (instance-slots-layout nil :type list) - (class-slots nil :type list)) + (slots () :type list)) #-sb-fluid (declaim (sb-ext:freeze-type wrapper)) ;;;; PCL's view of funcallable instances @@ -98,14 +117,23 @@ (import 'sb-kernel:funcallable-instance-p) (defun set-funcallable-instance-function (fin new-value) - (declare (type function new-value)) - (aver (funcallable-instance-p fin)) + (declare (type function new-value) + ;; KLUDGE: it might be nice to restrict + ;; SB-MOP:SET-FUNCALLABLE-INSTANCE-FUNCTION to operate only + ;; on generalized instances of + ;; SB-MOP:FUNCALLABLE-STANDARD-OBJECT; at present, even + ;; PCL's internal use of SET-FUNCALLABLE-INSTANCE-FUNCTION + ;; doesn't obey this restriction. + (type funcallable-instance fin)) (setf (funcallable-instance-fun fin) new-value)) + ;;; FIXME: these macros should just go away. It's not clear whether ;;; the inline functions defined by ;;; !DEFSTRUCT-WITH-ALTERNATE-METACLASS are as efficient as they could ;;; be; ordinary defstruct accessors are defined as source transforms. -(defmacro fsc-instance-p (fin) +(defun fsc-instance-p (fin) + (funcallable-instance-p fin)) +(define-compiler-macro fsc-instance-p (fin) `(funcallable-instance-p ,fin)) (defmacro fsc-instance-wrapper (fin) `(%funcallable-instance-layout ,fin)) @@ -127,7 +155,9 @@ ;;; and normal instances, so we can return true on structures also. A ;;; few uses of (OR STD-INSTANCE-P FSC-INSTANCE-P) are changed to ;;; PCL-INSTANCE-P. -(defmacro std-instance-p (x) +(defun std-instance-p (x) + (%instancep x)) +(define-compiler-macro std-instance-p (x) `(%instancep ,x)) ;; a temporary definition used for debugging the bootstrap @@ -146,17 +176,20 @@ ;;; this an interned symbol. That means that the fast check to see ;;; whether a slot is unbound is to say (EQ '..SLOT-UNBOUND..). ;;; That is considerably faster than looking at the value of a special -;;; variable. Be careful, there are places in the code which actually -;;; use ..SLOT-UNBOUND.. rather than this variable. So much for -;;; modularity.. +;;; variable. ;;; -;;; FIXME: Now that we're tightly integrated into SBCL, we could use -;;; the SBCL built-in unbound value token instead. Perhaps if we did -;;; so it would be a good idea to define collections of CLOS slots as -;;; a new type of heap object, instead of using bare SIMPLE-VECTOR, in -;;; order to avoid problems (in the debugger if nowhere else) with -;;; SIMPLE-VECTORs some of whose elements are unbound tokens. -(defconstant +slot-unbound+ '..slot-unbound..) +;;; It seems only reasonable to also export this for users, since +;;; otherwise dealing with STANDARD-INSTANCE-ACCESS becomes harder +;;; -- and slower -- than it needs to be. +(defconstant +slot-unbound+ '..slot-unbound.. + "SBCL specific extentions to MOP: if this value is read from an +instance using STANDARD-INSTANCE-ACCESS, the slot is unbound. +Similarly, an :INSTANCE allocated slot can be made unbound by +assigning this to it using (SETF STANDARD-INSTANCE-ACCESS). + +Value of +SLOT-UNBOUND+ is unspecified, and should not be relied to be +of any particular type, but it is guaranteed to be suitable for EQ +comparison.") (defmacro %allocate-static-slot-storage--class (no-of-slots) `(make-array ,no-of-slots :initial-element +slot-unbound+)) @@ -175,19 +208,20 @@ (defun set-fun-name (fun new-name) #+sb-doc "Set the name of a compiled function object. Return the function." - (declare (special *boot-state* *the-class-standard-generic-function*)) (when (valid-function-name-p fun) (setq fun (fdefinition fun))) - (when (funcallable-instance-p fun) - ;; HACK - (case (classoid-name (classoid-of fun)) - (%method-function (setf (%method-function-name fun) new-name)) - (t ;; KLUDGE: probably a generic function... - (if (if (eq *boot-state* 'complete) - (typep fun 'generic-function) - (eq (class-of fun) *the-class-standard-generic-function*)) - (setf (%funcallable-instance-info fun 2) new-name) - (bug "unanticipated function type"))))) + (typecase fun + (%method-function (setf (%method-function-name fun) new-name)) + #+sb-eval + (sb-eval:interpreted-function + (setf (sb-eval:interpreted-function-name fun) new-name)) + (funcallable-instance ;; KLUDGE: probably a generic function... + (cond ((if (eq **boot-state** 'complete) + (typep fun 'generic-function) + (eq (class-of fun) *the-class-standard-generic-function*)) + (setf (%funcallable-instance-info fun 2) new-name)) + (t + (bug "unanticipated function type"))))) ;; Fixup name-to-function mappings in cases where the function ;; hasn't been defined by DEFUN. (FIXME: is this right? This logic ;; comes from CMUCL). -- CSR, 2004-12-31 @@ -259,8 +293,6 @@ (when (pcl-instance-p instance) (get-slots instance))) -(defmacro built-in-or-structure-wrapper (x) `(layout-of ,x)) - (defmacro get-wrapper (inst) (once-only ((wrapper `(wrapper-of ,inst))) `(progn @@ -304,20 +336,29 @@ ;;; The definition of STRUCTURE-TYPE-P was moved to early-low.lisp. -(defun get-structure-dd (type) - (layout-info (classoid-layout (find-classoid type)))) - -(defun structure-type-included-type-name (type) - (let ((include (dd-include (get-structure-dd type)))) - (if (consp include) - (car include) - include))) - (defun structure-type-slot-description-list (type) - (nthcdr (length (let ((include (structure-type-included-type-name type))) - (and include - (dd-slots (get-structure-dd include))))) - (dd-slots (get-structure-dd type)))) + (let* ((dd (find-defstruct-description type)) + (include (dd-include dd)) + (all-slots (dd-slots dd))) + (multiple-value-bind (super slot-overrides) + (if (consp include) + (values (car include) (mapcar #'car (cdr include))) + (values include nil)) + (let ((included-slots + (when super + (dd-slots (find-defstruct-description super))))) + (loop for slot = (pop all-slots) + for included-slot = (pop included-slots) + while slot + when (or (not included-slot) + (member (dsd-name included-slot) slot-overrides :test #'eq)) + collect slot))))) + +(defun uninitialized-accessor-function (type slotd) + (lambda (&rest args) + (declare (ignore args)) + (error "~:(~A~) function~@[ for ~S ~] not yet initialized." + type slotd))) (defun structure-slotd-name (slotd) (dsd-name slotd)) @@ -326,13 +367,19 @@ (dsd-accessor-name slotd)) (defun structure-slotd-reader-function (slotd) - (fdefinition (dsd-accessor-name slotd))) + (let ((name (dsd-accessor-name slotd))) + (if (fboundp name) + (fdefinition name) + (uninitialized-accessor-function :reader slotd)))) (defun structure-slotd-writer-function (type slotd) (if (dsd-read-only slotd) - (let ((dd (get-structure-dd type))) + (let ((dd (find-defstruct-description type))) (coerce (slot-setter-lambda-form dd slotd) 'function)) - (fdefinition `(setf ,(dsd-accessor-name slotd))))) + (let ((name `(setf ,(dsd-accessor-name slotd)))) + (if (fboundp name) + (fdefinition name) + (uninitialized-accessor-function :writer slotd))))) (defun structure-slotd-type (slotd) (dsd-type slotd)) @@ -364,31 +411,7 @@ :slot-names (fast-function name) :boa-constructor %make-method-function :superclass-name function - :metaclass-name random-pcl-classoid - :metaclass-constructor make-random-pcl-classoid + :metaclass-name static-classoid + :metaclass-constructor make-static-classoid :dd-type funcallable-structure) - -;;; WITH-PCL-LOCK is used around some forms that were previously -;;; protected by WITHOUT-INTERRUPTS, but in a threaded SBCL we don't -;;; have a useful WITHOUT-INTERRUPTS. In an unthreaded SBCL I'm not -;;; sure what the desired effect is anyway: should we be protecting -;;; against the possibility of recursive calls into these functions -;;; or are we using WITHOUT-INTERRUPTS as WITHOUT-SCHEDULING? -;;; -;;; Users: FORCE-CACHE-FLUSHES, MAKE-INSTANCES-OBSOLETE. Note that -;;; it's not all certain this is sufficent for threadsafety: do we -;;; just have to protect against simultaneous calls to these mutators, -;;; or actually to stop normal slot access etc at the same time as one -;;; of them runs - -#+sb-thread -(progn - (defvar *pcl-lock* (sb-thread::make-spinlock)) - - (defmacro with-pcl-lock (&body body) - `(sb-thread::with-spinlock (*pcl-lock*) - ,@body))) - -#-sb-thread -(defmacro with-pcl-lock (&body body) - `(progn ,@body)) +