X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Flate-extensions.lisp;h=0d1febeece52465f2adcd48d7aa31621bf006a41;hb=a160917364f85b38dc0826a5e3dcef87e3c4c62c;hp=2e0a9df5a1c348646dace0c88ae3d84338429289;hpb=880a863592743d82835e0fb4395301d6ab1f5127;p=sbcl.git diff --git a/src/code/late-extensions.lisp b/src/code/late-extensions.lisp index 2e0a9df..0d1febe 100644 --- a/src/code/late-extensions.lisp +++ b/src/code/late-extensions.lisp @@ -48,12 +48,15 @@ ;;; Used internally, but it would be nice to provide something ;;; like this for users as well. - +;;; +;;; FIXME / IMPORTANT: If the slot is raw, the address is correct only for +;;; instances of the specified class, not its subclasses! #!+sb-thread (defmacro define-structure-slot-addressor (name &key structure slot) (let* ((dd (find-defstruct-description structure t)) (slotd (when dd (find slot (dd-slots dd) :key #'dsd-name))) - (index (when slotd (dsd-index slotd)))) + (index (when slotd (dsd-index slotd))) + (raw-type (dsd-raw-type slotd))) (unless index (error "Slot ~S not found in ~S." slot structure)) `(progn @@ -63,7 +66,11 @@ (sb!ext:truly-the sb!vm:word (+ (sb!kernel:get-lisp-obj-address instance) - (- (* ,(+ sb!vm:instance-slots-offset index) sb!vm:n-word-bytes) + (- (* ,(if (eq t raw-type) + (+ sb!vm:instance-slots-offset index) + (- (1+ (sb!kernel::dd-instance-length dd)) sb!vm:instance-slots-offset index + (1- (sb!kernel::raw-slot-words raw-type)))) + sb!vm:n-word-bytes) sb!vm:instance-pointer-lowtag))))))) (defmacro compare-and-swap (place old new &environment env) @@ -160,7 +167,7 @@ EXPERIMENTAL: Interface subject to change." (def %compare-and-swap-symbol-value (symbol) symbol-value) (def %compare-and-swap-svref (vector index) svref)) -(defmacro atomic-incf (place &optional (diff 1) &environment env) +(defmacro atomic-incf (place &optional (diff 1)) #!+sb-doc "Atomically increments PLACE by DIFF, and returns the value of PLACE before the increment. @@ -179,41 +186,40 @@ and (SIGNED-BYTE 64) on 64 bit platforms. EXPERIMENTAL: Interface subject to change." (flet ((invalid-place () (error "Invalid first argument to ATOMIC-INCF: ~S" place))) - (let ((place (macroexpand place env))) - (unless (consp place) + (unless (consp place) + (invalid-place)) + (destructuring-bind (op &rest args) place + (when (cdr args) (invalid-place)) - (destructuring-bind (op &rest args) place - (when (cdr args) - (invalid-place)) - (let ((dd (info :function :structure-accessor op))) - (if dd - (let* ((structure (dd-name dd)) - (slotd (find op (dd-slots dd) :key #'dsd-accessor-name)) - (index (dsd-index slotd)) - (type (dsd-type slotd))) - (declare (ignorable index)) - (unless (and (eq 'sb!vm:word (dsd-raw-type slotd)) - (type= (specifier-type type) (specifier-type 'sb!vm:word))) - (error "ATOMIC-INCF requires a slot of type (UNSIGNED-BYTE ~S), not ~S: ~S" - sb!vm:n-word-bits type place)) - (when (dsd-read-only slotd) - (error "Cannot use ATOMIC-INCF with structure accessor for a read-only slot: ~S" - place)) - #!+(or x86 x86-64) - `(truly-the sb!vm:word - (%raw-instance-atomic-incf/word (the ,structure ,@args) - ,index - (the sb!vm:signed-word ,diff))) - ;; No threads outside x86 and x86-64 for now, so this is easy... - #!-(or x86 x86-64) - (with-unique-names (structure old) - `(sb!sys:without-interrupts - (let* ((,structure ,@args) - (,old (,op ,structure))) - (setf (,op ,structure) (logand #.(1- (ash 1 sb!vm:n-word-bits)) - (+ ,old (the sb!vm:signed-word ,diff)))) - ,old)))) - (invalid-place))))))) + (let ((dd (info :function :structure-accessor op))) + (if dd + (let* ((structure (dd-name dd)) + (slotd (find op (dd-slots dd) :key #'dsd-accessor-name)) + (index (dsd-index slotd)) + (type (dsd-type slotd))) + (declare (ignorable structure index)) + (unless (and (eq 'sb!vm:word (dsd-raw-type slotd)) + (type= (specifier-type type) (specifier-type 'sb!vm:word))) + (error "ATOMIC-INCF requires a slot of type (UNSIGNED-BYTE ~S), not ~S: ~S" + sb!vm:n-word-bits type place)) + (when (dsd-read-only slotd) + (error "Cannot use ATOMIC-INCF with structure accessor for a read-only slot: ~S" + place)) + #!+(or x86 x86-64) + `(truly-the sb!vm:word + (%raw-instance-atomic-incf/word (the ,structure ,@args) + ,index + (the sb!vm:signed-word ,diff))) + ;; No threads outside x86 and x86-64 for now, so this is easy... + #!-(or x86 x86-64) + (with-unique-names (structure old) + `(sb!sys:without-interrupts + (let* ((,structure ,@args) + (,old (,op ,structure))) + (setf (,op ,structure) (logand #.(1- (ash 1 sb!vm:n-word-bits)) + (+ ,old (the sb!vm:signed-word ,diff)))) + ,old)))) + (invalid-place)))))) (defun call-hooks (kind hooks &key (on-error :error)) (dolist (hook hooks)