1.0.10.5: dynamic-extent CONS
[sbcl/simd.git] / src / compiler / x86 / alloc.lisp
blob59d47f5fb3ddccc378dd06fadc972355eccfac41
1 ;;;; allocation VOPs for the x86
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
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.
12 (in-package "SB!VM")
14 ;;;; CONS, LIST and LIST*
15 (defoptimizer (cons stack-allocate-result) ((&rest args))
17 (defoptimizer (list stack-allocate-result) ((&rest args))
18 (not (null args)))
19 (defoptimizer (list* stack-allocate-result) ((&rest args))
20 (not (null (rest args))))
22 (define-vop (list-or-list*)
23 (:args (things :more t))
24 (:temporary (:sc unsigned-reg) ptr temp)
25 (:temporary (:sc unsigned-reg :to (:result 0) :target result) res)
26 (:info num)
27 (:results (result :scs (descriptor-reg)))
28 (:variant-vars star)
29 (:policy :safe)
30 (:node-var node)
31 (:generator 0
32 (cond ((zerop num)
33 ;; (move result nil-value)
34 (inst mov result nil-value))
35 ((and star (= num 1))
36 (move result (tn-ref-tn things)))
38 (macrolet
39 ((store-car (tn list &optional (slot cons-car-slot))
40 `(let ((reg
41 (sc-case ,tn
42 ((any-reg descriptor-reg) ,tn)
43 ((control-stack)
44 (move temp ,tn)
45 temp))))
46 (storew reg ,list ,slot list-pointer-lowtag))))
47 (let ((cons-cells (if star (1- num) num)))
48 (pseudo-atomic
49 (allocation res (* (pad-data-block cons-size) cons-cells) node
50 (awhen (sb!c::node-lvar node) (sb!c::lvar-dynamic-extent it)))
51 (inst lea res
52 (make-ea :byte :base res :disp list-pointer-lowtag))
53 (move ptr res)
54 (dotimes (i (1- cons-cells))
55 (store-car (tn-ref-tn things) ptr)
56 (setf things (tn-ref-across things))
57 (inst add ptr (pad-data-block cons-size))
58 (storew ptr ptr (- cons-cdr-slot cons-size)
59 list-pointer-lowtag))
60 (store-car (tn-ref-tn things) ptr)
61 (cond (star
62 (setf things (tn-ref-across things))
63 (store-car (tn-ref-tn things) ptr cons-cdr-slot))
65 (storew nil-value ptr cons-cdr-slot
66 list-pointer-lowtag)))
67 (aver (null (tn-ref-across things)))))
68 (move result res))))))
70 (define-vop (list list-or-list*)
71 (:variant nil))
73 (define-vop (list* list-or-list*)
74 (:variant t))
76 ;;;; special-purpose inline allocators
78 ;;; ALLOCATE-VECTOR
79 (define-vop (allocate-vector-on-heap)
80 (:args (type :scs (unsigned-reg immediate))
81 (length :scs (any-reg immediate))
82 (words :scs (any-reg immediate)))
83 (:results (result :scs (descriptor-reg) :from :load))
84 (:arg-types positive-fixnum
85 positive-fixnum
86 positive-fixnum)
87 (:policy :fast-safe)
88 (:generator 100
89 (let ((size (sc-case words
90 (immediate
91 (logandc2 (+ (fixnumize (tn-value words))
92 (+ (1- (ash 1 n-lowtag-bits))
93 (* vector-data-offset n-word-bytes)))
94 lowtag-mask))
96 (inst lea result (make-ea :byte :base words :disp
97 (+ (1- (ash 1 n-lowtag-bits))
98 (* vector-data-offset
99 n-word-bytes))))
100 (inst and result (lognot lowtag-mask))
101 result))))
102 (pseudo-atomic
103 (allocation result size)
104 (inst lea result (make-ea :byte :base result :disp other-pointer-lowtag))
105 (sc-case type
106 (immediate
107 (aver (typep (tn-value type) '(unsigned-byte 8)))
108 (storeb (tn-value type) result 0 other-pointer-lowtag))
110 (storew type result 0 other-pointer-lowtag)))
111 (sc-case length
112 (immediate
113 (let ((fixnum-length (fixnumize (tn-value length))))
114 (typecase fixnum-length
115 ((unsigned-byte 8)
116 (storeb fixnum-length result
117 vector-length-slot other-pointer-lowtag))
119 (storew fixnum-length result
120 vector-length-slot other-pointer-lowtag)))))
122 (storew length result vector-length-slot other-pointer-lowtag)))))))
124 (define-vop (allocate-vector-on-stack)
125 (:args (type :scs (unsigned-reg immediate))
126 (length :scs (any-reg))
127 (words :scs (any-reg) :target ecx))
128 (:temporary (:sc any-reg :offset ecx-offset :from (:argument 2)) ecx)
129 (:temporary (:sc any-reg :offset eax-offset :from (:argument 2)) zero)
130 (:temporary (:sc any-reg :offset edi-offset :from (:argument 0)) res)
131 (:results (result :scs (descriptor-reg) :from :load))
132 (:arg-types positive-fixnum
133 positive-fixnum
134 positive-fixnum)
135 (:translate allocate-vector)
136 (:policy :fast-safe)
137 (:node-var node)
138 (:generator 100
139 (inst lea result (make-ea :byte :base words :disp
140 (+ (1- (ash 1 n-lowtag-bits))
141 (* vector-data-offset n-word-bytes))))
142 (inst and result (lognot lowtag-mask))
143 ;; FIXME: It would be good to check for stack overflow here.
144 (move ecx words)
145 (inst shr ecx n-fixnum-tag-bits)
146 (allocation result result node t)
147 (inst cld)
148 (inst lea res
149 (make-ea :byte :base result :disp (* vector-data-offset n-word-bytes)))
150 (inst lea result (make-ea :byte :base result :disp other-pointer-lowtag))
151 (sc-case type
152 (immediate
153 (aver (typep (tn-value type) '(unsigned-byte 8)))
154 (storeb (tn-value type) result 0 other-pointer-lowtag))
156 (storew type result 0 other-pointer-lowtag)))
157 (storew length result vector-length-slot other-pointer-lowtag)
158 (inst xor zero zero)
159 (inst rep)
160 (inst stos zero)))
162 (in-package "SB!C")
164 (defoptimizer (allocate-vector stack-allocate-result)
165 ((type length words) node)
166 (ecase (policy node stack-allocate-vector)
167 (0 nil)
168 ((1 2)
169 ;; a vector object should fit in one page
170 (values-subtypep (lvar-derived-type words)
171 (load-time-value
172 (specifier-type `(integer 0 ,(- (/ sb!vm::*backend-page-size*
173 sb!vm:n-word-bytes)
174 sb!vm:vector-data-offset))))))
175 (3 t)))
177 (defoptimizer (allocate-vector ltn-annotate) ((type length words) call ltn-policy)
178 (let ((args (basic-combination-args call))
179 (template (template-or-lose (if (awhen (node-lvar call)
180 (lvar-dynamic-extent it))
181 'sb!vm::allocate-vector-on-stack
182 'sb!vm::allocate-vector-on-heap))))
183 (dolist (arg args)
184 (setf (lvar-info arg)
185 (make-ir2-lvar (primitive-type (lvar-type arg)))))
186 (unless (is-ok-template-use template call (ltn-policy-safe-p ltn-policy))
187 (ltn-default-call call)
188 (return-from allocate-vector-ltn-annotate-optimizer (values)))
189 (setf (basic-combination-info call) template)
190 (setf (node-tail-p call) nil)
192 (dolist (arg args)
193 (annotate-1-value-lvar arg))))
195 (in-package "SB!VM")
198 (define-vop (allocate-code-object)
199 (:args (boxed-arg :scs (any-reg) :target boxed)
200 (unboxed-arg :scs (any-reg) :target unboxed))
201 (:results (result :scs (descriptor-reg) :from :eval))
202 (:temporary (:sc unsigned-reg :from (:argument 0)) boxed)
203 (:temporary (:sc unsigned-reg :from (:argument 1)) unboxed)
204 (:node-var node)
205 (:generator 100
206 (move boxed boxed-arg)
207 (inst add boxed (fixnumize (1+ code-trace-table-offset-slot)))
208 (inst and boxed (lognot lowtag-mask))
209 (move unboxed unboxed-arg)
210 (inst shr unboxed word-shift)
211 (inst add unboxed lowtag-mask)
212 (inst and unboxed (lognot lowtag-mask))
213 (inst mov result boxed)
214 (inst add result unboxed)
215 (pseudo-atomic
216 (allocation result result node)
217 (inst lea result (make-ea :byte :base result :disp other-pointer-lowtag))
218 (inst shl boxed (- n-widetag-bits word-shift))
219 (inst or boxed code-header-widetag)
220 (storew boxed result 0 other-pointer-lowtag)
221 (storew unboxed result code-code-size-slot other-pointer-lowtag)
222 (storew nil-value result code-entry-points-slot other-pointer-lowtag))
223 (storew nil-value result code-debug-info-slot other-pointer-lowtag)))
225 (define-vop (make-fdefn)
226 (:policy :fast-safe)
227 (:translate make-fdefn)
228 (:args (name :scs (descriptor-reg) :to :eval))
229 (:results (result :scs (descriptor-reg) :from :argument))
230 (:node-var node)
231 (:generator 37
232 (with-fixed-allocation (result fdefn-widetag fdefn-size node)
233 (storew name result fdefn-name-slot other-pointer-lowtag)
234 (storew nil-value result fdefn-fun-slot other-pointer-lowtag)
235 (storew (make-fixup "undefined_tramp" :foreign)
236 result fdefn-raw-addr-slot other-pointer-lowtag))))
238 (define-vop (make-closure)
239 (:args (function :to :save :scs (descriptor-reg)))
240 (:info length stack-allocate-p)
241 (:temporary (:sc any-reg) temp)
242 (:results (result :scs (descriptor-reg)))
243 (:node-var node)
244 (:generator 10
245 (maybe-pseudo-atomic stack-allocate-p
246 (let ((size (+ length closure-info-offset)))
247 (allocation result (pad-data-block size) node
248 stack-allocate-p)
249 (inst lea result
250 (make-ea :byte :base result :disp fun-pointer-lowtag))
251 (storew (logior (ash (1- size) n-widetag-bits) closure-header-widetag)
252 result 0 fun-pointer-lowtag))
253 (loadw temp function closure-fun-slot fun-pointer-lowtag)
254 (storew temp result closure-fun-slot fun-pointer-lowtag))))
256 ;;; The compiler likes to be able to directly make value cells.
257 (define-vop (make-value-cell)
258 (:args (value :scs (descriptor-reg any-reg) :to :result))
259 (:results (result :scs (descriptor-reg) :from :eval))
260 (:info stack-allocate-p)
261 (:node-var node)
262 (:generator 10
263 (with-fixed-allocation
264 (result value-cell-header-widetag value-cell-size node stack-allocate-p)
265 (storew value result value-cell-value-slot other-pointer-lowtag))))
267 ;;;; automatic allocators for primitive objects
269 (define-vop (make-unbound-marker)
270 (:args)
271 (:results (result :scs (any-reg)))
272 (:generator 1
273 (inst mov result unbound-marker-widetag)))
275 (define-vop (make-funcallable-instance-tramp)
276 (:args)
277 (:results (result :scs (any-reg)))
278 (:generator 1
279 (inst lea result (make-fixup "funcallable_instance_tramp" :foreign))))
281 (define-vop (fixed-alloc)
282 (:args)
283 (:info name words type lowtag stack-allocate-p)
284 (:ignore name)
285 (:results (result :scs (descriptor-reg)))
286 (:node-var node)
287 (:generator 50
288 ;; We special case the allocation of conses, because they're
289 ;; extremely common and because the pseudo-atomic sequence on x86
290 ;; is relatively heavyweight. However, if the user asks for top
291 ;; speed, we accomodate him. The primary reason that we don't
292 ;; also check for (< SPEED SPACE) is because we want the space
293 ;; savings that these out-of-line allocation routines bring whilst
294 ;; compiling SBCL itself. --njf, 2006-07-08
295 (if (and (not stack-allocate-p)
296 (= lowtag list-pointer-lowtag) (policy node (< speed 3)))
297 (let ((dst
298 ;; FIXME: out-of-line dx-allocation
299 #.(loop for offset in *dword-regs*
300 collect `(,offset
301 ',(intern (format nil "ALLOCATE-CONS-TO-~A"
302 (svref *dword-register-names*
303 offset)))) into cases
304 finally (return `(case (tn-offset result)
305 ,@cases)))))
306 (aver (null type))
307 (inst call (make-fixup dst :assembly-routine)))
308 (pseudo-atomic
309 (allocation result (pad-data-block words) node stack-allocate-p)
310 (inst lea result (make-ea :byte :base result :disp lowtag))
311 (when type
312 (storew (logior (ash (1- words) n-widetag-bits) type)
313 result
315 lowtag))))))
317 (define-vop (var-alloc)
318 (:args (extra :scs (any-reg)))
319 (:arg-types positive-fixnum)
320 (:info name words type lowtag)
321 (:ignore name)
322 (:results (result :scs (descriptor-reg) :from (:eval 1)))
323 (:temporary (:sc any-reg :from :eval :to (:eval 1)) bytes)
324 (:temporary (:sc any-reg :from :eval :to :result) header)
325 (:node-var node)
326 (:generator 50
327 (inst lea bytes
328 (make-ea :dword :base extra :disp (* (1+ words) n-word-bytes)))
329 (inst mov header bytes)
330 (inst shl header (- n-widetag-bits 2)) ; w+1 to length field
331 (inst lea header ; (w-1 << 8) | type
332 (make-ea :dword :base header :disp (+ (ash -2 n-widetag-bits) type)))
333 (inst and bytes (lognot lowtag-mask))
334 (pseudo-atomic
335 (allocation result bytes node)
336 (inst lea result (make-ea :byte :base result :disp lowtag))
337 (storew header result 0 lowtag))))