1.0.29.38: better DESCRIBE
[sbcl.git] / src / compiler / mips / alloc.lisp
1 ;;;; allocation VOPs for Mips
2
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.
11
12 (in-package "SB!VM")
13 \f
14 ;;;; LIST and LIST*
15 (define-vop (list-or-list*)
16   (:args (things :more t))
17   (:temporary (:scs (descriptor-reg) :type list) ptr)
18   (:temporary (:scs (descriptor-reg)) temp)
19   (:temporary (:scs (descriptor-reg) :type list :to (:result 0) :target result)
20               res)
21   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
22   (:info num)
23   (:results (result :scs (descriptor-reg)))
24   (:variant-vars star)
25   (:policy :safe)
26   (:node-var node)
27   (:generator 0
28     (cond ((zerop num)
29            (move result null-tn))
30           ((and star (= num 1))
31            (move result (tn-ref-tn things)))
32           (t
33            (macrolet
34                ((store-car (tn list &optional (slot cons-car-slot))
35                   `(let ((reg
36                           (sc-case ,tn
37                             ((any-reg descriptor-reg zero null)
38                              ,tn)
39                             (control-stack
40                              (load-stack-tn temp ,tn)
41                              temp))))
42                      (storew reg ,list ,slot list-pointer-lowtag))))
43              (let* ((dx-p (node-stack-allocate-p node))
44                     (cons-cells (if star (1- num) num))
45                     (alloc (* (pad-data-block cons-size) cons-cells)))
46                (pseudo-atomic (pa-flag :extra (if dx-p 0 alloc))
47                  (when dx-p
48                    (align-csp res))
49                  (inst srl res (if dx-p csp-tn alloc-tn) n-lowtag-bits)
50                  (inst sll res n-lowtag-bits)
51                  (inst or res list-pointer-lowtag)
52                  (when dx-p
53                    (inst addu csp-tn alloc))
54                  (move ptr res)
55                  (dotimes (i (1- cons-cells))
56                    (store-car (tn-ref-tn things) ptr)
57                    (setf things (tn-ref-across things))
58                    (inst addu ptr ptr (pad-data-block cons-size))
59                    (storew ptr ptr
60                            (- cons-cdr-slot cons-size)
61                            list-pointer-lowtag))
62                  (store-car (tn-ref-tn things) ptr)
63                  (cond (star
64                         (setf things (tn-ref-across things))
65                         (store-car (tn-ref-tn things) ptr cons-cdr-slot))
66                        (t
67                         (storew null-tn ptr
68                                 cons-cdr-slot list-pointer-lowtag)))
69                  (aver (null (tn-ref-across things)))
70                  (move result res))))))))
71
72 (define-vop (list list-or-list*)
73   (:variant nil))
74
75 (define-vop (list* list-or-list*)
76   (:variant t))
77 \f
78 ;;;; Special purpose inline allocators.
79
80 ;;; ALLOCATE-VECTOR
81 (define-vop (allocate-vector-on-heap)
82   (:args (type :scs (unsigned-reg))
83          (length :scs (any-reg))
84          (words :scs (any-reg)))
85   (:arg-types positive-fixnum
86               positive-fixnum
87               positive-fixnum)
88   (:temporary (:sc non-descriptor-reg) bytes)
89   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
90   (:results (result :scs (descriptor-reg) :from :load))
91   (:policy :fast-safe)
92   (:generator 100
93     (inst addu bytes words (+ lowtag-mask
94                               (* vector-data-offset n-word-bytes)))
95     (inst srl bytes n-lowtag-bits)
96     (inst sll bytes n-lowtag-bits)
97     (pseudo-atomic (pa-flag)
98       (inst or result alloc-tn other-pointer-lowtag)
99       (inst addu alloc-tn bytes)
100       (storew type result 0 other-pointer-lowtag)
101       (storew length result vector-length-slot other-pointer-lowtag))))
102
103 (define-vop (allocate-vector-on-stack)
104   (:args (type :scs (unsigned-reg))
105          (length :scs (any-reg))
106          (words :scs (any-reg)))
107   (:arg-types positive-fixnum
108               positive-fixnum
109               positive-fixnum)
110   (:temporary (:sc non-descriptor-reg) bytes)
111   (:temporary (:sc non-descriptor-reg) temp)
112   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
113   (:results (result :scs (descriptor-reg) :from :load))
114   (:policy :fast-safe)
115   (:generator 100
116     (inst addu bytes words (+ lowtag-mask
117                               (* vector-data-offset n-word-bytes)))
118     (inst srl bytes n-lowtag-bits)
119     (inst sll bytes n-lowtag-bits)
120     ;; FIXME: It would be good to check for stack overflow here.
121     (pseudo-atomic (pa-flag)
122       (align-csp temp)
123       (inst or result csp-tn other-pointer-lowtag)
124       (inst addu temp csp-tn (* vector-data-offset n-word-bytes))
125       (inst addu csp-tn bytes)
126       (storew type result 0 other-pointer-lowtag)
127       (storew length result vector-length-slot other-pointer-lowtag)
128       (let ((loop (gen-label)))
129         (emit-label loop)
130         (storew zero-tn temp 0)
131         (inst bne temp csp-tn loop)
132         (inst addu temp n-word-bytes))
133       (align-csp temp))))
134
135 (define-vop (allocate-code-object)
136   (:args (boxed-arg :scs (any-reg))
137          (unboxed-arg :scs (any-reg)))
138   (:results (result :scs (descriptor-reg)))
139   (:temporary (:scs (non-descriptor-reg)) ndescr)
140   (:temporary (:scs (any-reg) :from (:argument 0)) boxed)
141   (:temporary (:scs (non-descriptor-reg) :from (:argument 1)) unboxed)
142   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
143   (:generator 100
144     (inst li ndescr (lognot lowtag-mask))
145     (inst addu boxed boxed-arg
146           (fixnumize (1+ code-trace-table-offset-slot)))
147     (inst and boxed ndescr)
148     (inst srl unboxed unboxed-arg word-shift)
149     (inst addu unboxed unboxed lowtag-mask)
150     (inst and unboxed ndescr)
151     (inst sll ndescr boxed (- n-widetag-bits word-shift))
152     (inst or ndescr code-header-widetag)
153
154     (pseudo-atomic (pa-flag)
155       (inst or result alloc-tn other-pointer-lowtag)
156       (inst addu alloc-tn boxed)
157       (storew ndescr result 0 other-pointer-lowtag)
158       (storew unboxed result code-code-size-slot other-pointer-lowtag)
159       (inst addu alloc-tn unboxed)
160       (storew null-tn result code-entry-points-slot other-pointer-lowtag)
161       (storew null-tn result code-debug-info-slot other-pointer-lowtag))))
162
163 (define-vop (make-fdefn)
164   (:policy :fast-safe)
165   (:translate make-fdefn)
166   (:args (name :scs (descriptor-reg) :to :eval))
167   (:temporary (:scs (non-descriptor-reg)) temp)
168   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
169   (:results (result :scs (descriptor-reg) :from :argument))
170   (:generator 37
171     (with-fixed-allocation (result pa-flag temp fdefn-widetag fdefn-size nil)
172       (inst li temp (make-fixup "undefined_tramp" :foreign))
173       (storew name result fdefn-name-slot other-pointer-lowtag)
174       (storew null-tn result fdefn-fun-slot other-pointer-lowtag)
175       (storew temp result fdefn-raw-addr-slot other-pointer-lowtag))))
176
177 (define-vop (make-closure)
178   (:args (function :to :save :scs (descriptor-reg)))
179   (:info length stack-allocate-p)
180   (:temporary (:scs (non-descriptor-reg)) temp)
181   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
182   (:results (result :scs (descriptor-reg)))
183   (:generator 10
184     (let* ((size (+ length closure-info-offset))
185            (alloc-size (pad-data-block size)))
186       (pseudo-atomic (pa-flag :extra (if stack-allocate-p 0 alloc-size))
187         (cond (stack-allocate-p
188                (align-csp result)
189                (inst srl result csp-tn n-lowtag-bits)
190                (inst addu csp-tn alloc-size))
191               (t
192                (inst srl result alloc-tn n-lowtag-bits)))
193         (inst sll result n-lowtag-bits)
194         (inst or result fun-pointer-lowtag)
195         (inst li temp (logior (ash (1- size) n-widetag-bits)
196                               closure-header-widetag))
197         (storew temp result 0 fun-pointer-lowtag)
198         (storew function result closure-fun-slot fun-pointer-lowtag)))))
199
200 ;;; The compiler likes to be able to directly make value cells.
201 (define-vop (make-value-cell)
202   (:args (value :to :save :scs (descriptor-reg any-reg null zero)))
203   (:temporary (:scs (non-descriptor-reg)) temp)
204   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
205   (:info stack-allocate-p)
206   (:results (result :scs (descriptor-reg)))
207   (:generator 10
208     (with-fixed-allocation (result pa-flag temp value-cell-header-widetag
209                             value-cell-size stack-allocate-p)
210       (storew value result value-cell-value-slot other-pointer-lowtag))))
211 \f
212 ;;;; Automatic allocators for primitive objects.
213
214 (define-vop (make-unbound-marker)
215   (:args)
216   (:results (result :scs (any-reg)))
217   (:generator 1
218     (inst li result unbound-marker-widetag)))
219
220 (define-vop (make-funcallable-instance-tramp)
221   (:args)
222   (:results (result :scs (any-reg)))
223   (:generator 1
224     (inst li result (make-fixup "funcallable_instance_tramp" :foreign))))
225
226 (define-vop (fixed-alloc)
227   (:args)
228   (:info name words type lowtag stack-allocate-p)
229   (:ignore name)
230   (:results (result :scs (descriptor-reg)))
231   (:temporary (:scs (non-descriptor-reg)) temp)
232   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
233   (:generator 4
234     (pseudo-atomic (pa-flag :extra (if stack-allocate-p
235                                        0
236                                        (pad-data-block words)))
237       (cond (stack-allocate-p
238              (align-csp result)
239              (inst or result csp-tn lowtag)
240              (inst addu csp-tn (pad-data-block words)))
241             (t
242              ;; The pseudo-atomic bit in alloc-tn is set.  If the
243              ;; lowtag also has a 1 bit in the same position, we're all
244              ;; set.  Otherwise, we need to subtract the pseudo-atomic
245              ;; bit.
246              (inst or result alloc-tn (if (logbitp 0 lowtag) lowtag
247                                                              (1- lowtag)))))
248       (when type
249         (inst li temp (logior (ash (1- words) n-widetag-bits) type))
250         (storew temp result 0 lowtag)))))
251
252 (define-vop (var-alloc)
253   (:args (extra :scs (any-reg)))
254   (:arg-types positive-fixnum)
255   (:info name words type lowtag)
256   (:ignore name)
257   (:results (result :scs (descriptor-reg)))
258   (:temporary (:scs (any-reg)) bytes)
259   (:temporary (:scs (non-descriptor-reg)) header)
260   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
261   (:generator 6
262     (inst addu bytes extra (* (1+ words) n-word-bytes))
263     (inst sll header bytes (- n-widetag-bits 2))
264     (inst addu header header (+ (ash -2 n-widetag-bits) type))
265     (inst srl bytes bytes n-lowtag-bits)
266     (inst sll bytes bytes n-lowtag-bits)
267     (pseudo-atomic (pa-flag)
268       (inst or result alloc-tn lowtag)
269       (storew header result 0 lowtag)
270       (inst addu alloc-tn alloc-tn bytes))))
271