1 ;;;; allocating simple objects
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 ;;;; Signed and unsigned bignums from word-sized integers. Argument
15 ;;;; and return in the same register. No VOPs, as these are only used
16 ;;;; as out-of-line versions: MOVE-FROM-[UN]SIGNED VOPs handle the
17 ;;;; fixnum cases inline.
19 ;;; #+SB-ASSEMBLING as we don't need VOPS, just the asm routines:
20 ;;; these are out-of-line versions called by VOPs.
24 (let ((tn (symbolicate reg
"-TN")))
25 `(define-assembly-routine (,(symbolicate "ALLOC-SIGNED-BIGNUM-IN-" reg
)) ()
27 (with-fixed-allocation (,tn bignum-widetag
(+ bignum-digits-offset
1))
28 (popw ,tn bignum-digits-offset other-pointer-lowtag
))))))
38 (let ((tn (symbolicate reg
"-TN")))
39 `(define-assembly-routine (,(symbolicate "ALLOC-UNSIGNED-BIGNUM-IN-" reg
)) ()
41 ;; Sign flag is set by the caller! Note: The inline
42 ;; version always allocates space for two words, but
43 ;; here we minimize garbage.
44 (inst jmp
:ns one-word-bignum
)
46 (with-fixed-allocation (,tn bignum-widetag
(+ bignum-digits-offset
2))
47 (popw ,tn bignum-digits-offset other-pointer-lowtag
))
50 (with-fixed-allocation (,tn bignum-widetag
(+ bignum-digits-offset
1))
51 (popw ,tn bignum-digits-offset other-pointer-lowtag
))))))
59 ;;; FIXME: This is dead, right? Can it go?
61 (defun frob-allocation-assembly-routine (obj lowtag arg-tn
)
62 `(define-assembly-routine (,(intern (format nil
"ALLOCATE-~A-TO-~A" obj arg-tn
)))
63 ((:temp
,arg-tn descriptor-reg
,(intern (format nil
"~A-OFFSET" arg-tn
))))
65 (allocation ,arg-tn
(pad-data-block ,(intern (format nil
"~A-SIZE" obj
))))
66 (inst lea
,arg-tn
(make-ea :byte
:base
,arg-tn
:disp
,lowtag
)))))
69 (macrolet ((frob-cons-routines ()
71 (dolist (tn-offset *dword-regs
*
73 (push (frob-allocation-assembly-routine 'cons
75 (intern (aref +dword-register-names
+ tn-offset
)))
80 (define-assembly-routine (alloc-tls-index
81 (:translate ensure-symbol-tls-index
)
82 (:result-types positive-fixnum
)
84 ;; The vop result is unsigned-reg because the assembly routine does not
85 ;; fixnumize its answer, which is confusing because it looks like a fixnum.
86 ;; But the result of the function ENSURE-SYMBOL-TLS-INDEX is a fixnum whose
87 ;; value in Lisp is the number that the assembly code computes,
88 ;; *not* the fixnum whose representation it computes.
89 ((:arg symbol
(descriptor-reg) eax-offset
) ; both input and output
90 (:res result
(unsigned-reg) eax-offset
))
91 (let ((scratch-reg ecx-tn
) ; ECX gets callee-saved, not declared as a temp
92 (free-tls-index-ea (make-ea-for-symbol-value *free-tls-index
*))
93 (lock-bit 31) ; sign bit
94 (tls-full (gen-label)))
95 ;; A pseudo-atomic section avoids bad behavior if the current thread were
96 ;; to receive an interrupt causing it to do a slow operation between
97 ;; acquisition and release of the spinlock. Preventing GC is irrelevant,
98 ;; but would not be if we recycled tls indices of garbage symbols.
100 (assemble () ; for conversion of tagbody-like labels to assembler labels
102 (inst bts free-tls-index-ea lock-bit
:lock
)
103 (inst jmp
:nc got-tls-index-lock
)
104 (inst pause
) ; spin loop hint
105 ;; TODO: yielding the CPU here might be a good idea
108 ;; Now we hold the spinlock. With it held, see if the symbol's
109 ;; tls-index has been set in the meantime.
110 (inst cmp
(tls-index-of symbol
) 0)
111 (inst jmp
:e new-tls-index
)
112 ;; TLS index is valid, so use it.
113 (inst and
(make-ea :byte
:disp
(+ (ea-disp free-tls-index-ea
) 3)) #x7F
114 :lock
) ; set the spinlock bit to 0
117 ;; Allocate a new tls-index.
118 (inst push scratch-reg
)
119 (inst mov scratch-reg free-tls-index-ea
)
120 (inst and scratch-reg
#x7FFFFFFF
) ; mask off the sign
121 (inst cmp scratch-reg
(* tls-size n-word-bytes
))
122 (inst jmp
:ae tls-full
)
123 ;; Assign the tls-index into the symbol
124 (inst mov
(tls-index-of symbol
) scratch-reg
)
125 ;; Bump the free index and clear the lock.
126 (inst add scratch-reg n-word-bytes
)
127 (inst mov free-tls-index-ea scratch-reg
)
128 (inst pop scratch-reg
)
130 (inst mov result
(tls-index-of symbol
)))) ; end PSEUDO-ATOMIC
132 (emit-label tls-full
)
133 (inst mov free-tls-index-ea scratch-reg
) ; unlock
134 (inst pop scratch-reg
) ; balance the stack
135 (%clear-pseudo-atomic
)
136 ;; There's a spurious RET instruction auto-inserted, but no matter.
137 (error-call nil
'tls-exhausted-error
)))