(:ignore name)
(:results)
(:generator 1
- (if (sc-is value immediate)
- (let ((val (tn-value value)))
- (etypecase val
- (integer
- (inst mov
- (make-ea :dword :base object
- :disp (- (* offset n-word-bytes) lowtag))
- (fixnumize val)))
- (symbol
- (inst mov
- (make-ea :dword :base object
- :disp (- (* offset n-word-bytes) lowtag))
- (+ nil-value (static-symbol-offset val))))
- (character
- (inst mov
- (make-ea :dword :base object
- :disp (- (* offset n-word-bytes) lowtag))
- (logior (ash (char-code val) n-widetag-bits)
- character-widetag)))))
- ;; Else, value not immediate.
- (storew value object offset lowtag))))
-\f
-
+ (storew (encode-value-if-immediate value) object offset lowtag)))
+(define-vop (compare-and-swap-slot)
+ (:args (object :scs (descriptor-reg) :to :eval)
+ (old :scs (descriptor-reg any-reg) :target eax)
+ (new :scs (descriptor-reg any-reg)))
+ (:temporary (:sc descriptor-reg :offset eax-offset
+ :from (:argument 1) :to :result :target result)
+ eax)
+ (:info name offset lowtag)
+ (:ignore name)
+ (:results (result :scs (descriptor-reg any-reg)))
+ (:generator 5
+ (move eax old)
+ #!+sb-thread
+ (inst lock)
+ (inst cmpxchg (make-ea :dword :base object
+ :disp (- (* offset n-word-bytes) lowtag))
+ new)
+ (move result eax)))
+\f
;;;; symbol hacking VOPs
+(define-vop (%compare-and-swap-symbol-value)
+ (:translate %compare-and-swap-symbol-value)
+ (:args (symbol :scs (descriptor-reg) :to (:result 1))
+ (old :scs (descriptor-reg any-reg) :target eax)
+ (new :scs (descriptor-reg any-reg)))
+ (:temporary (:sc descriptor-reg :offset eax-offset) eax)
+ #!+sb-thread
+ (:temporary (:sc descriptor-reg) tls)
+ (:results (result :scs (descriptor-reg any-reg)))
+ (:policy :fast-safe)
+ (:vop-var vop)
+ (:generator 15
+ ;; This code has to pathological cases: NO-TLS-VALUE-MARKER
+ ;; or UNBOUND-MARKER as NEW: in either case we would end up
+ ;; doing possible damage with CMPXCHG -- so don't do that!
+ (let ((unbound (generate-error-code vop 'unbound-symbol-error symbol))
+ (check (gen-label)))
+ (move eax old)
+ #!+sb-thread
+ (progn
+ (loadw tls symbol symbol-tls-index-slot other-pointer-lowtag)
+ ;; Thread-local area, no LOCK needed.
+ (inst fs-segment-prefix)
+ (inst cmpxchg (make-ea :dword :base tls) new)
+ (inst cmp eax no-tls-value-marker-widetag)
+ (inst jmp :ne check)
+ (move eax old)
+ (inst lock))
+ (inst cmpxchg (make-ea :dword :base symbol
+ :disp (- (* symbol-value-slot n-word-bytes)
+ other-pointer-lowtag))
+ new)
+ (emit-label check)
+ (move result eax)
+ (inst cmp result unbound-marker-widetag)
+ (inst jmp :e unbound))))
+
;;; these next two cf the sparc version, by jrd.
;;; FIXME: Deref this ^ reference.
(let ((global-val (gen-label))
(done (gen-label)))
(loadw tls symbol symbol-tls-index-slot other-pointer-lowtag)
- (inst or tls tls)
- (inst jmp :z global-val)
(inst fs-segment-prefix)
(inst cmp (make-ea :dword :base tls) no-tls-value-marker-widetag)
(inst jmp :z global-val)
(define-vop (set cell-set)
(:variant symbol-value-slot other-pointer-lowtag))
-;;; Do a cell ref with an error check for being unbound.
-;;; XXX stil used? I can't see where -dan
-(define-vop (checked-cell-ref)
- (:args (object :scs (descriptor-reg) :target obj-temp))
- (:results (value :scs (descriptor-reg any-reg)))
- (:policy :fast-safe)
- (:vop-var vop)
- (:save-p :compute-only)
- (:temporary (:sc descriptor-reg :from (:argument 0)) obj-temp))
-
;;; With Symbol-Value, we check that the value isn't the trap object. So
;;; Symbol-Value of NIL is NIL.
#!+sb-thread
(:save-p :compute-only)
(:generator 9
(let* ((check-unbound-label (gen-label))
- (err-lab (generate-error-code vop unbound-symbol-error object))
+ (err-lab (generate-error-code vop 'unbound-symbol-error object))
(ret-lab (gen-label)))
(loadw value object symbol-tls-index-slot other-pointer-lowtag)
(inst fs-segment-prefix)
(:vop-var vop)
(:save-p :compute-only)
(:generator 9
- (let ((err-lab (generate-error-code vop unbound-symbol-error object)))
+ (let ((err-lab (generate-error-code vop 'unbound-symbol-error object)))
(loadw value object symbol-value-slot other-pointer-lowtag)
(inst cmp value unbound-marker-widetag)
(inst jmp :e err-lab))))
(:generator 4
(move result value)
(inst lock)
- (inst add (make-ea :dword :base object
- :disp (- (* symbol-value-slot n-word-bytes)
- other-pointer-lowtag))
+ (inst add (make-ea-for-object-slot object symbol-value-slot
+ other-pointer-lowtag)
value)))
#!+sb-thread
(:generator 10
(loadw value object fdefn-fun-slot other-pointer-lowtag)
(inst cmp value nil-value)
- (let ((err-lab (generate-error-code vop undefined-fun-error object)))
+ (let ((err-lab (generate-error-code vop 'undefined-fun-error object)))
(inst jmp :e err-lab))))
(define-vop (set-fdefn-fun)
(:generator 38
(load-type type function (- fun-pointer-lowtag))
(inst lea raw
- (make-ea :byte :base function
- :disp (- (* simple-fun-code-offset n-word-bytes)
- fun-pointer-lowtag)))
+ (make-ea-for-object-slot function simple-fun-code-offset
+ fun-pointer-lowtag))
(inst cmp type simple-fun-header-widetag)
(inst jmp :e normal-fn)
(inst lea raw (make-fixup "closure_tramp" :foreign))
;;; the symbol on the binding stack and stuff the new value into the
;;; symbol.
+;;; FIXME: Split into DYNBIND and BIND: DYNBIND needs to ensure
+;;; TLS-INDEX, whereas BIND should assume it is already in place. Make
+;;; LET &co compile into BIND, and PROGV into DYNBIND, plus ensure
+;;; TLS-INDEX at compile-time, and make loader and dumper preserve
+;;; the existence of a TLS-INDEX.
#!+sb-thread
(define-vop (bind)
(:args (val :scs (any-reg descriptor-reg))
(symbol :scs (descriptor-reg)))
- (:temporary (:sc descriptor-reg :offset eax-offset) eax)
- (:temporary (:sc unsigned-reg) tls-index temp bsp)
+ (:temporary (:sc unsigned-reg) tls-index bsp)
(:generator 10
- (let ((tls-index-valid (gen-label))
- (get-tls-index-lock (gen-label))
- (release-tls-index-lock (gen-label)))
+ (let ((tls-index-valid (gen-label)))
(load-binding-stack-pointer bsp)
(loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
(inst add bsp (* binding-size n-word-bytes))
(store-binding-stack-pointer bsp)
(inst or tls-index tls-index)
(inst jmp :ne tls-index-valid)
-
- (pseudo-atomic
- (emit-label get-tls-index-lock)
- (inst mov temp 1)
- (inst xor eax eax)
- (inst lock)
- (inst cmpxchg (make-ea-for-symbol-value *tls-index-lock*) temp)
- (inst jmp :ne get-tls-index-lock)
- ;; now with the lock held, see if the symbol's tls index has
- ;; been set in the meantime
- (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
- (inst or tls-index tls-index)
- (inst jmp :ne release-tls-index-lock)
- ;; allocate a new tls-index
- (load-symbol-value tls-index *free-tls-index*)
- (inst add tls-index 4) ;XXX surely we can do this more
- (store-symbol-value tls-index *free-tls-index*) ;succintly
- (inst sub tls-index 4)
- (storew tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
- (emit-label release-tls-index-lock)
- (store-symbol-value 0 *tls-index-lock*))
-
+ (inst mov tls-index symbol)
+ (inst call (make-fixup
+ (ecase (tn-offset tls-index)
+ (#.eax-offset 'alloc-tls-index-in-eax)
+ (#.ebx-offset 'alloc-tls-index-in-ebx)
+ (#.ecx-offset 'alloc-tls-index-in-ecx)
+ (#.edx-offset 'alloc-tls-index-in-edx)
+ (#.edi-offset 'alloc-tls-index-in-edi)
+ (#.esi-offset 'alloc-tls-index-in-esi))
+ :assembly-routine))
(emit-label tls-index-valid)
(inst fs-segment-prefix)
- (inst mov temp (make-ea :dword :base tls-index))
- (storew temp bsp (- binding-value-slot binding-size))
+ (inst push (make-ea :dword :base tls-index))
+ (popw bsp (- binding-value-slot binding-size))
(storew symbol bsp (- binding-symbol-slot binding-size))
(inst fs-segment-prefix)
(inst mov (make-ea :dword :base tls-index) val))))
(storew symbol bsp (- binding-symbol-slot binding-size))
(storew val symbol symbol-value-slot other-pointer-lowtag)))
-
#!+sb-thread
(define-vop (unbind)
- ;; four temporaries?
- (:temporary (:sc unsigned-reg) symbol value bsp tls-index)
+ (:temporary (:sc unsigned-reg) temp bsp tls-index)
(:generator 0
(load-binding-stack-pointer bsp)
- (loadw symbol bsp (- binding-symbol-slot binding-size))
- (loadw value bsp (- binding-value-slot binding-size))
-
- (loadw tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
+ ;; Load SYMBOL from stack, and get the TLS-INDEX.
+ (loadw temp bsp (- binding-symbol-slot binding-size))
+ (loadw tls-index temp symbol-tls-index-slot other-pointer-lowtag)
+ ;; Load VALUE from stack, then restore it to the TLS area.
+ (loadw temp bsp (- binding-value-slot binding-size))
(inst fs-segment-prefix)
- (inst mov (make-ea :dword :base tls-index) value)
-
- (storew 0 bsp (- binding-value-slot binding-size))
+ (inst mov (make-ea :dword :base tls-index) temp)
+ ;; Zero out the stack.
(storew 0 bsp (- binding-symbol-slot binding-size))
+ (storew 0 bsp (- binding-value-slot binding-size))
(inst sub bsp (* binding-size n-word-bytes))
(store-binding-stack-pointer bsp)))
(loadw symbol bsp (- binding-symbol-slot binding-size))
(loadw value bsp (- binding-value-slot binding-size))
(storew value symbol symbol-value-slot other-pointer-lowtag)
- (storew 0 bsp (- binding-value-slot binding-size))
(storew 0 bsp (- binding-symbol-slot binding-size))
+ (storew 0 bsp (- binding-value-slot binding-size))
(inst sub bsp (* binding-size n-word-bytes))
(store-symbol-value bsp *binding-stack-pointer*)))
(loadw symbol bsp (- binding-symbol-slot binding-size))
(inst or symbol symbol)
(inst jmp :z skip)
+ ;; Bind stack debug sentinels have the unbound marker in the symbol slot
+ (inst cmp symbol unbound-marker-widetag)
+ (inst jmp :eq skip)
(loadw value bsp (- binding-value-slot binding-size))
#!-sb-thread (storew value symbol symbol-value-slot other-pointer-lowtag)
tls-index symbol symbol-tls-index-slot other-pointer-lowtag)
#!+sb-thread (inst fs-segment-prefix)
#!+sb-thread (inst mov (make-ea :dword :base tls-index) value)
- (storew 0 bsp (- binding-value-slot binding-size))
(storew 0 bsp (- binding-symbol-slot binding-size))
SKIP
+ (storew 0 bsp (- binding-value-slot binding-size))
(inst sub bsp (* binding-size n-word-bytes))
(inst cmp where bsp)
(inst jmp :ne loop)
(store-binding-stack-pointer bsp)
DONE))
+
+(define-vop (bind-sentinel)
+ (:temporary (:sc unsigned-reg) bsp)
+ (:generator 1
+ (load-binding-stack-pointer bsp)
+ (inst add bsp (* binding-size n-word-bytes))
+ (storew unbound-marker-widetag bsp (- binding-symbol-slot binding-size))
+ (storew ebp-tn bsp (- binding-value-slot binding-size))
+ (store-binding-stack-pointer bsp)))
+
+(define-vop (unbind-sentinel)
+ (:temporary (:sc unsigned-reg) bsp)
+ (:generator 1
+ (load-binding-stack-pointer bsp)
+ (storew 0 bsp (- binding-value-slot binding-size))
+ (storew 0 bsp (- binding-symbol-slot binding-size))
+ (inst sub bsp (* binding-size n-word-bytes))
+ (store-binding-stack-pointer bsp)))
\f
\f
(loadw res struct 0 instance-pointer-lowtag)
(inst shr res n-widetag-bits)))
-(define-full-reffer instance-index-ref * instance-slots-offset
- instance-pointer-lowtag (any-reg descriptor-reg) * %instance-ref)
-
-(define-full-setter instance-index-set * instance-slots-offset
- instance-pointer-lowtag (any-reg descriptor-reg) * %instance-set)
-
-
-(defknown %instance-set-conditional (instance index t t) t
- (unsafe))
-
-(define-vop (instance-set-conditional)
- (:translate %instance-set-conditional)
- (:args (object :scs (descriptor-reg) :to :eval)
- (slot :scs (any-reg) :to :result)
- (old-value :scs (descriptor-reg any-reg) :target eax)
- (new-value :scs (descriptor-reg any-reg)))
- (:arg-types instance positive-fixnum * *)
- (:temporary (:sc descriptor-reg :offset eax-offset
- :from (:argument 2) :to :result :target result) eax)
- (:results (result :scs (descriptor-reg any-reg)))
- ;(:guard (backend-featurep :i486))
- (:policy :fast-safe)
- (:generator 5
- (move eax old-value)
- (inst lock)
- (inst cmpxchg (make-ea :dword :base object :index slot :scale 1
- :disp (- (* instance-slots-offset n-word-bytes)
- instance-pointer-lowtag))
- new-value)
- (move result eax)))
+(define-full-reffer instance-index-ref *
+ instance-slots-offset instance-pointer-lowtag
+ (any-reg descriptor-reg) *
+ %instance-ref)
+(define-full-setter instance-index-set *
+ instance-slots-offset instance-pointer-lowtag
+ (any-reg descriptor-reg) *
+ %instance-set)
+(define-full-compare-and-swap %compare-and-swap-instance-ref instance
+ instance-slots-offset instance-pointer-lowtag
+ (any-reg descriptor-reg) *
+ %compare-and-swap-instance-ref)
\f
;;;; code object frobbing
(define-full-setter code-header-set * 0 other-pointer-lowtag
(any-reg descriptor-reg) * code-header-set)
-
-
\f
;;;; raw instance slot accessors