tests: Avoid nonsensical classes and methods in deprecation.impure.lisp
[sbcl.git] / src / compiler / policy.lisp
blobf821122f2ed05a3c8275823b4e7b1f83a2ba6631
1 ;;;; compiler optimization policy stuff
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!C")
14 ;;; a value for an optimization declaration
15 (def!type policy-quality () '(integer 0 3))
17 (defvar *macro-policy* nil)
18 ;;; global policy restrictions as a POLICY object or nil
19 (defvar *policy-min* nil)
20 (defvar *policy-max* nil)
22 (defun restrict-compiler-policy (&optional quality (min 0) (max 3))
23 "Assign a minimum value to an optimization quality. QUALITY is the name of
24 the optimization quality to restrict, MIN (defaulting to zero) is the
25 minimum allowed value, and MAX (defaults to 3) is the maximum.
27 Returns the alist describing the current policy restrictions.
29 If QUALITY is NIL or not given, nothing is done.
31 Otherwise, if MIN is zero or MAX is 3 or neither are given, any
32 existing restrictions of QUALITY are removed.
34 See also :POLICY option in WITH-COMPILATION-UNIT."
35 (declare (type policy-quality min max))
36 (when quality
37 (let ((quality-id (policy-quality-name-p quality)))
38 (unless quality-id
39 (error "~S is not a policy quality" quality))
40 (when (> min max)
41 (error "MIN ~s should be not be greater than MAX ~s." min max))
42 ;; The dynamic policy object is immutable, otherwise a construct like
43 ;; (let ((*policy-min* *policy-max*)) ...)
44 ;; could allow alterations inside the LET to leak out.
45 ;; The structure itself does not declare slots its read-only, because
46 ;; OPTIMIZE declaration processing uses it as a scratchpad.
47 (setf *policy-min*
48 (if *policy-min*
49 (copy-structure *policy-min*)
50 (make-policy 0 0))
51 *policy-max*
52 (if *policy-max*
53 (copy-structure *policy-max*)
54 (let ((policy (make-policy
55 (1- (expt 2 (* 2 n-policy-primary-qualities)))
56 0)))
57 (setf (policy-dependent-qualities policy)
58 (1- (expt 2
59 (* (- max-policy-qualities n-policy-primary-qualities)
60 2))))
61 policy)))
62 (alter-policy *policy-min* quality-id min (plusp min))
63 (alter-policy *policy-max* quality-id max (< max 3))))
64 ;; Return dotted pairs, not elements that look declaration-like.
65 (flet ((policy-to-result (policy)
66 (and policy
67 (mapc (lambda (x) (rplacd x (cadr x)))
68 (policy-to-decl-spec policy)))))
69 (values (policy-to-result *policy-min*)
70 (policy-to-result *policy-max*))))
72 (defstruct (policy-dependent-quality (:copier nil))
73 (name nil :type symbol :read-only t)
74 (expression nil :read-only t)
75 (getter nil :read-only t)
76 (values-documentation nil :read-only t))
78 ;;; names of recognized optimization policy qualities
79 (declaim (simple-vector **policy-dependent-qualities**))
80 (defglobal **policy-dependent-qualities** #())
82 ;; Return POLICY as a list suitable to the OPTIMIZE declaration.
83 ;; If FORCE-ALL then include qualities without an explicit value too.
84 (defun policy-to-decl-spec (policy &optional (raw t) force-all)
85 (loop with presence = (policy-presence-bits policy)
86 for index from (- n-policy-primary-qualities)
87 below (length **policy-dependent-qualities**)
88 when (or force-all (logbitp (mod index max-policy-qualities) presence))
89 collect
90 (list (if (minusp index)
91 (elt **policy-primary-qualities** (lognot index))
92 (policy-dependent-quality-name
93 (elt **policy-dependent-qualities** index)))
94 (if raw
95 ;; Raw values are insensitive to *POLICY-MIN/MAX*.
96 (%%policy-quality policy index)
97 ;; Otherwise take the adjusted quality.
98 (%policy-quality policy index)))))
100 ;; Return T if P1 and P2 are policies which are specified to be the same.
101 ;; A result of NIL does not imply that definitely P1 /= P2
102 ;; because a multitude of policies can be effectively equal.
103 ;; [Any dependent quality might be specified the same as its computed
104 ;; value in the absence of an explicit value.]
105 (defun policy= (p1 p2)
106 (or (and p1 p2
107 (= (policy-primary-qualities p1) (policy-primary-qualities p2))
108 (= (policy-dependent-qualities p1) (policy-dependent-qualities p2))
109 (= (policy-presence-bits p1) (policy-presence-bits p2)))
110 (and (null p1) (null p2))))
112 ;;; Is X the name of an optimization policy quality?
113 ;;; If it is, return the integer identifier for the quality name.
114 (defun policy-quality-name-p (x)
115 ;; Standard (and non-standard) primary qualities are numbered from -1 down.
116 (or (awhen (position x **policy-primary-qualities** :test #'eq)
117 (lognot it))
118 ;; Dependent qualities are numbered from 0 up.
119 (position x **policy-dependent-qualities**
120 :key #'policy-dependent-quality-name)))
122 ;; Destructively modify POLICY such that quality INDEX has VALUE,
123 ;; and the specified PRESENTP bit.
124 (defun alter-policy (policy index value &optional (presentp t))
125 (if (minusp index) ; a primary quality
126 (setf (ldb (byte 2 (* 2 (lognot index)))
127 (policy-primary-qualities policy)) value)
128 (setf (ldb (byte 2 (* 2 index))
129 (policy-dependent-qualities policy)) value))
130 ;; Some cross-compilation hosts can't execute (SETF (LOGBITP ...)).
131 (setf (ldb (byte 1 (mod index max-policy-qualities))
132 (policy-presence-bits policy)) (if presentp 1 0))
133 policy)
135 ;;; Is it deprecated?
136 (declaim (ftype function deprecation-warn))
137 (defun policy-quality-deprecation-warning (quality)
138 (case quality
139 ((stack-allocate-dynamic-extent stack-allocate-vector stack-allocate-value-cells)
140 (deprecation-warn :late "SBCL" "1.0.19.7" 'policy quality '*stack-allocate-dynamic-extent*
141 :runtime-error nil)
143 ((merge-tail-calls)
144 (deprecation-warn :early "SBCL" "1.0.53.74" 'policy quality nil :runtime-error nil)
146 (otherwise
147 nil)))
149 ;;; *POLICY* holds the current global compiler policy information, as
150 ;;; a POLICY object mapping from the compiler-assigned index (unique per
151 ;;; quality name) to quality value.
152 ;;; This used to be an alist, but tail-sharing was never really possible
153 ;;; because for deterministic comparison the list was always freshly
154 ;;; consed so that destructive sorting could be done for canonicalization.
155 (declaim (type policy *policy*)
156 (type (or policy null) *policy-min* *policy-max*))
158 ;; ANSI-specified default of 1 for each quality.
159 (defglobal **baseline-policy** nil)
160 ;; Baseline policy altered with (TYPE-CHECK 0)
161 (defglobal **zero-typecheck-policy** nil)
162 #-sb-xc-host (declaim (type policy **baseline-policy**))
164 ;;; This is to be called early in cold init to set things up, and may
165 ;;; also be called again later in cold init in order to reset default
166 ;;; optimization policy back to default values after toplevel PROCLAIM
167 ;;; OPTIMIZE forms have messed with it.
168 (defun !policy-cold-init-or-resanify ()
169 (setq **baseline-policy**
170 (make-policy (loop for i below n-policy-primary-qualities
171 sum (ash #b01 (* i 2))))
172 **zero-typecheck-policy**
173 (alter-policy (copy-policy **baseline-policy**)
174 #-sb-xc (policy-quality-name-p 'type-check)
175 ;; Eval in the host since cold-init won't have
176 ;; executed any forms in 'policies.lisp'
177 #+sb-xc #.(policy-quality-name-p 'type-check)
180 ;; CMU CL didn't use 1 as the default for everything,
181 ;; but since ANSI says 1 is the ordinary value, we do.
182 (setf *policy* (copy-policy **baseline-policy**)))
184 ;;; Look up a named optimization quality in POLICY. This is only
185 ;;; called by compiler code for known-valid QUALITY-NAMEs, e.g. SPEED;
186 ;;; it's an error if it's called for a quality which isn't defined.
187 (defun policy-quality (policy quality-name)
188 (%policy-quality policy
189 (the fixnum (policy-quality-name-p quality-name))))
191 (define-compiler-macro policy-quality (&whole form policy quality-name)
192 (acond ((and (constantp quality-name)
193 ;; CONSTANT-FORM-VALUE can not be called here when building
194 ;; the cross-compiler, but EVAL can safely be used
195 ;; since our own source code is known not to be screwy.
196 (policy-quality-name-p (#-sb-xc-host constant-form-value
197 #+sb-xc-host eval quality-name)))
198 `(%policy-quality ,policy ,it))
200 form)))
202 (macrolet ((extract-field (min-expression-primary min-expression-dependent
203 max-expression-primary max-expression-dependent)
204 `(if (minusp index)
205 (let ((byte-pos (* (lognot index) 2)))
206 (min ,max-expression-primary
207 (max ,min-expression-primary
208 (ldb (byte 2 byte-pos)
209 (policy-primary-qualities policy)))))
210 (let ((byte-pos (* index 2)))
211 (min ,max-expression-dependent
212 (max ,min-expression-dependent
213 (if (logbitp index (policy-presence-bits policy))
214 (ldb (byte 2 byte-pos)
215 (policy-dependent-qualities policy))
216 1))))))
217 (define-getter (name &body body)
218 `(defun ,name (policy index)
219 (declare (type policy policy)
220 (type (integer
221 #.(- n-policy-primary-qualities)
222 #.(- max-policy-qualities
223 n-policy-primary-qualities 1))
224 index))
225 ,@body)))
227 ;; Return the value for quality INDEX in POLICY, using *POLICY-MIN/MAX*
228 ;; Primary qualities are assumed to exist, however policy-restricting functions
229 ;; can create a POLICY that indicates absence of primary qualities.
230 ;; This does not affect RESTRICT-COMPILER-POLICY because a lower bound of 0
231 ;; can be assumed for everything. SET-MACRO-POLICY might care though.
232 (define-getter %policy-quality
233 (let ((min *policy-min*)
234 (max *policy-max*))
235 (macrolet ((quality-min (get-byte)
236 `(if min
237 (ldb (byte 2 byte-pos) (,get-byte min))
239 (quality-max (get-byte)
240 `(if max
241 (ldb (byte 2 byte-pos) (,get-byte max))
242 3)))
243 (extract-field (quality-min policy-primary-qualities)
244 (quality-min policy-dependent-qualities)
245 (quality-max policy-primary-qualities)
246 (quality-max policy-dependent-qualities)))))
248 ;; Return the unadjusted value for quality INDEX in POLICY.
249 ;; This is used for converting a policy to a list of elements for display
250 ;; and for verifying that after processing declarations, the new policy
251 ;; matches the given declarations, thus implying no ambiguity.
252 (define-getter %%policy-quality
253 (extract-field 0 0 3 3)))
255 ;;; Forward declaration of %COERCE-TO-POLICY.
256 ;;; Definition is in 'node' so that FUNCTIONAL and NODE types are defined.
257 ;;; Arg is declared of type T because the function explicitly checks it.
258 (declaim (ftype (sfunction (t) policy) %coerce-to-policy))
260 ;;; syntactic sugar for querying optimization policy qualities
262 ;;; Evaluate EXPR in terms of the optimization policy associated with
263 ;;; THING. EXPR is a form which accesses optimization qualities by
264 ;;; referring to them by name, e.g. (> SPEED SPACE).
265 (defmacro policy (thing expr &optional (coercion-fn '%coerce-to-policy))
266 (let* ((n-policy (make-symbol "P"))
267 (binds (loop for name across **policy-primary-qualities**
268 for index downfrom -1
269 collect `(,name (%policy-quality ,n-policy ,index))))
270 (dependent-binds
271 (loop for info across **policy-dependent-qualities**
272 for name = (policy-dependent-quality-name info)
273 collect `(,name (let ((,name (policy-quality ,n-policy ',name)))
274 (if (= ,name 1)
275 ,(policy-dependent-quality-expression info)
276 ,name))))))
277 `(let ((,n-policy (,coercion-fn ,thing)))
278 ;; FIXME: automatically inserted IGNORABLE decls are
279 ;; often suggestive of poor style, as is this one.
280 (declare (ignorable ,n-policy))
281 (symbol-macrolet (,@binds ,@dependent-binds)
282 ,expr))))
284 ;;; Dependent qualities
285 (defmacro define-optimization-quality
286 (name expression &optional values-documentation documentation)
287 (declare (ignorable documentation))
288 `(eval-when (:compile-toplevel :load-toplevel :execute)
289 (let ((number (policy-quality-name-p ',name))
290 (item (make-policy-dependent-quality
291 :name ',name
292 :expression ',expression
293 ;; DESCRIBE-COMPILER-POLICY uses the getter
294 :getter (named-lambda ,(string name) (policy)
295 (policy policy ,expression))
296 :values-documentation ',values-documentation)))
297 (if number
298 (setf (svref **policy-dependent-qualities** number) item)
299 ;; This array is reallocated every time a policy is added,
300 ;; but that's fine - it's not a performance issue.
301 (let ((size (1+ (length **policy-dependent-qualities**))))
302 ;; Don't overrun the packed bit fields.
303 (when (> (+ n-policy-primary-qualities size) max-policy-qualities)
304 (error "Maximum number of policy qualities exceeded."))
305 (setf **policy-dependent-qualities**
306 (replace (make-array size :initial-element item)
307 **policy-dependent-qualities**)))))
308 #-sb-xc-host
309 ,@(when documentation `((setf (fdocumentation ',name 'optimize) ,documentation)))
310 ',name))
312 ;;; Return a new POLICY containing the policy information represented
313 ;;; by the optimize declaration SPEC. Any parameters not specified are
314 ;;; defaulted from the POLICY argument.
315 (declaim (ftype (function (list (or policy null)) (values policy list))
316 process-optimize-decl))
317 (defun process-optimize-decl (spec policy)
318 (let ((result (copy-policy (or policy **baseline-policy**)))
319 (specified-qualities))
320 ;; Add new entries from SPEC.
321 (dolist (q-and-v-or-just-q (cdr spec) (values result specified-qualities))
322 (multiple-value-bind (quality raw-value)
323 (if (atom q-and-v-or-just-q)
324 (values q-and-v-or-just-q 3)
325 (destructuring-bind (quality raw-value) q-and-v-or-just-q
326 (values quality raw-value)))
327 (let ((index (policy-quality-name-p quality)))
328 (cond ((not index)
329 (or (policy-quality-deprecation-warning quality)
330 (compiler-warn
331 "~@<Ignoring unknown optimization quality ~S in:~_ ~S~:>"
332 quality spec)))
333 ((not (typep raw-value 'policy-quality))
334 (compiler-warn
335 "~@<Ignoring bad optimization value ~S in:~_ ~S~:>"
336 raw-value spec))
338 ;; we can't do this yet, because CLOS macros expand
339 ;; into code containing INHIBIT-WARNINGS.
340 #+nil
341 (when (eql quality 'inhibit-warnings)
342 (compiler-style-warn "~S is deprecated: use ~S instead"
343 quality 'muffle-conditions))
344 (push (cons quality raw-value) specified-qualities)
345 (alter-policy result index raw-value))))))))
347 ;;; Same as above but slightly more efficient
348 (defun %augment-policy (quality value policy)
349 (let ((result (copy-policy policy)))
350 (alter-policy result quality value)))
352 (defmacro augment-policy (quality value policy)
353 (let ((value-sym (gensym "VALUE"))
354 (policy-sym (gensym "POLICY")))
355 `(let ((,value-sym ,value)
356 (,policy-sym ,policy))
357 (if (policy ,policy-sym (> ,quality ,value-sym))
358 (%augment-policy ,(policy-quality-name-p quality)
359 ,value-sym
360 ,policy-sym)
361 ,policy-sym))))
363 (defvar *macro-policy* nil)
364 ;; Set an alternate policy that is used to compile all code within DEFMACRO,
365 ;; MACROLET, DEFINE-COMPILER-MARO - whether they occur at toplevel or not -
366 ;; as well as execute all toplevel code in eval-when situation :COMPILE-TOPLEVEL,
367 ;; including such code as emitted into a '.cfasl' file.
368 ;; e.g. (SET-MACRO-POLICY '((SPEED 0) (SAFETY 3))) ensures full error checking
369 ;; regardless of prevailing local policy in situations such as
370 ;; (macrolet ((frob (a b) (declare (type (member :up :down) a)) ...)
372 ;; Todo: it would be nice to allow NOTINLINE, which can be broadly achieved by
373 ;; setting (SPEED 0), but nonetheless more targeted settings should be possible.
374 ;; Same for {UN}MUFFLE-CONDITIONS or anything else that can be proclaimed.
376 (defun set-macro-policy (list)
377 ;: Note that *MACRO-POLICY* does not represent absence of any primary quality,
378 ;; and therefore whenever it is injected into a macro, you get all baseline
379 ;; values of 1, augmented by the specified changes.
380 ;; There are two alternative behaviors that might make sense:
381 ;; - use the value of *POLICY* when SET-MACRO-POLICY is called as the baseline
382 ;; augmented by the specifiers in LIST
383 ;; - use the lexical policy at the time of expansion, augmented by LIST
384 ;; But most probably the current behavior is entirely reasonable.
385 (setq *macro-policy* (process-optimize-decl `(optimize ,@list)
386 **baseline-policy**)))
388 ;; Turn the macro policy into an OPTIMIZE declaration for insertion
389 ;; into a macro body for DEFMACRO, MACROLET, or DEFINE-COMPILER-MACRO.
390 ;; Note that despite it being a style-warning to insert a duplicate,
391 ;; we need no precaution against that even though users may write
392 ;; (DEFMACRO FOO (X) (DECLARE (OPTIMIZE (SAFETY 1))) ...)
393 ;; The expansion of macro-defining forms is such that the macro-policy
394 ;; appears in a different lexical scope from the user's declarations.
395 (defun macro-policy-decls ()
396 (and *macro-policy*
397 `((declare (optimize ,@(policy-to-decl-spec *macro-policy*))))))