1 ;;;; This file contains functions that hack on the global function
2 ;;;; namespace (primarily concerned with SETF functions here). Also,
3 ;;;; function encapsulation and routines that set and return
4 ;;;; definitions disregarding whether they might be encapsulated.
6 ;;;; This software is part of the SBCL system. See the README file for
9 ;;;; This software is derived from the CMU CL system, which was
10 ;;;; written at Carnegie Mellon University and released into the
11 ;;;; public domain. The software is in the public domain and is
12 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
13 ;;;; files for more information.
15 (in-package "SB-IMPL")
18 ;;;; fdefinition (fdefn) objects
20 (defun make-fdefn (name)
21 #-
(and x86-64 immobile-space
) (make-fdefn name
)
22 #+(and x86-64 immobile-space
)
23 (let ((fdefn (truly-the (values fdefn
&optional
)
24 (sb-vm::alloc-immobile-fdefn
))))
25 (%primitive sb-vm
::set-slot fdefn name
'make-fdefn
26 sb-vm
:fdefn-name-slot sb-vm
:other-pointer-lowtag
)
27 (fdefn-makunbound fdefn
)
30 (defun undo-static-linkage (fdefn) (declare (ignore fdefn
)))
32 (defun (setf fdefn-fun
) (fun fdefn
)
33 (declare (type function fun
)
35 (undo-static-linkage fdefn
)
36 (sb-c::when-vop-existsp
(:named sb-vm
::set-fdefn-fun
)
37 (%primitive sb-vm
::set-fdefn-fun fun fdefn
))
38 (sb-c::unless-vop-existsp
(:named sb-vm
::set-fdefn-fun
)
39 (sb-vm::set-fdefn-fun fun fdefn
))
42 ;;; Return the FDEFN object for NAME, or NIL if there is no fdefn.
43 ;;; Signal an error if name isn't valid.
44 ;;; Assume that exists-p implies LEGAL-FUN-NAME-P.
45 (declaim (ftype (sfunction ((or symbol list
)) (or fdefn null
)) find-fdefn
))
46 (defun find-fdefn (name)
47 (declare (explicit-check))
48 (when (symbolp name
) ; Don't need LEGAL-FUN-NAME-P check
49 (let ((fdefn (sb-vm::%symbol-fdefn name
))) ; slot default is 0, not NIL
50 (return-from find-fdefn
(if (eql fdefn
0) nil fdefn
))))
51 ;; Technically the ALLOW-ATOM argument of NIL isn't needed, but
52 ;; the compiler isn't figuring out not to test SYMBOLP twice in a row.
53 (with-globaldb-name (key1 key2 nil
) name
55 (awhen (get-fancily-named-fdefn name nil
)
56 (return-from find-fdefn it
))
59 (awhen (symbol-dbinfo key1
)
60 (multiple-value-bind (data-idx descriptor-idx field-idx
)
61 (info-find-aux-key/packed it key2
)
62 (declare (type index descriptor-idx
)
63 (type (integer 0 #.
+infos-per-word
+) field-idx
))
64 ;; Secondary names must have at least one info, so if a descriptor
65 ;; exists, there's no need to extract the n-infos field.
67 (when (eql (incf field-idx
) +infos-per-word
+)
68 (setq field-idx
0 descriptor-idx
(1+ descriptor-idx
)))
69 (when (eql (packed-info-field it descriptor-idx field-idx
)
71 (return-from find-fdefn
72 (%info-ref it
(1- (the index data-idx
))))))))
73 (when (eq key1
'setf
) ; bypass the legality test
74 (return-from find-fdefn nil
))))
75 (legal-fun-name-or-type-error name
))
77 ;;; Return T if FUNCTION is the error-signaling trampoline for a macro or a
78 ;;; special operator. Test for this by seeing whether FUNCTION is the same
79 ;;; closure as for a known macro.
80 (declaim (inline macro
/special-guard-fun-p
))
81 (defun macro/special-guard-fun-p
(function)
82 ;; When inlined, this is a few instructions shorter than CLOSUREP
83 ;; if we already know that FUNCTION is a function.
84 ;; It will signal a type error if not, which is the right thing to do anyway.
85 ;; (this isn't quite a true predicate)
86 (and (= (%fun-pointer-widetag function
) sb-vm
:closure-widetag
)
87 ;; This test needs to reference the name of any macro, but in order for
88 ;; cold-init to work, the macro has to be defined first.
89 ;; So pick DX-LET, as it's in primordial-extensions.
90 ;; Prior to cold-init fixing up the load-time-value, this compares
91 ;; %closure-fun to 0, which is ok - it returns NIL.
92 (eq (load-time-value (%closure-fun
(symbol-function 'dx-let
)) t
)
93 (%closure-fun function
))))
95 ;;; This is the implementation of (COERCE s 'function) when S is of type symbol
96 ;;; used by either the full call or the compile-time transform for that pattern.
97 (defun coerce-symbol-to-fun (symbol)
98 (let ((def (%symbol-function symbol
)))
99 (cond ((not def
) (error 'undefined-function
:name symbol
))
100 ((macro/special-guard-fun-p def
)
101 (error (ecase (car (%fun-name def
))
102 (:macro
"~S names a macro.")
103 (:special
"~S names a special operator."))
107 (defglobal *fdefn-of-nil
* 0) ; God help you if you access this damn thing
108 (declaim (ftype (sfunction (t) fdefn
) find-or-create-fdefn
))
109 (defun find-or-create-fdefn (name)
112 (let ((fdefn (sb-vm::%symbol-fdefn name
)))
113 (if (or (eq fdefn nil
) (eq fdefn
0))
114 (let* ((new (make-fdefn name
))
117 (sb-vm::cas-symbol-fdefn name
0 new
)
118 (cas *fdefn-of-nil
* 0 new
))))
119 (if (eql actual
0) new
(the fdefn actual
)))
123 ;; We won't reach here if the name was not legal
125 (dx-flet ((new (name)
128 (let ((fdefn (with-globaldb-name (key1 key2
) name
129 :simple
(get-info-value-initializing
130 :function
:definition name
(new name
))
131 :hairy
(get-fancily-named-fdefn name
#'new
))))
132 ;; Slot accessors spring into existence as soon as a reference
133 ;; is made to the respective fdefn, but we can't do this in
134 ;; (flet NEW) because ENSURE-ACCESSOR calls (SETF FDEFINITION)
135 ;; which would recurse, as the fdefn would not have been
138 (typep name
'(cons (eql sb-pcl
::slot-accessor
))))
139 (sb-pcl::ensure-accessor name
))
142 ;;; Remove NAME's FTYPE information unless it was explicitly PROCLAIMED.
143 ;;; The NEW-FUNCTION argument is presently unused, but could be used
144 ;;; for checking compatibility of the NEW-FUNCTION against a proclamation.
145 ;;; (We could issue a warning and/or remove the type if incompatible.)
146 (defun maybe-clobber-ftype (name new-function
)
147 (declare (ignore new-function
))
148 ;; Ignore PCL-internal function names.
149 (unless (pcl-methodfn-name-p name
)
150 (unless (eq :declared
(info :function
:where-from name
))
151 (clear-info :function
:type name
))))
153 ;;; Return the fdefn-fun of NAME's fdefinition including any
154 ;;; encapsulations. This is the core of the implementation of the standard
155 ;;; FDEFINITION function, but as we've defined FDEFINITION, that
156 ;;; strips encapsulations.
157 (defun %coerce-name-to-fun
(name)
159 ((and symbol
(not null
))
160 (let ((fun (%symbol-function name
)))
161 (when (and fun
(not (macro/special-guard-fun-p fun
)))
162 (return-from %coerce-name-to-fun fun
))))
164 (binding* ((fdefn (find-fdefn name
) :exit-if-null
)
165 (fun (fdefn-fun fdefn
) :exit-if-null
))
166 (return-from %coerce-name-to-fun fun
))))
167 ;; We explicitly allow any function name when retrying,
168 ;; even if the erring caller was SYMBOL-FUNCTION. It is consistent
169 ;; that both #'(SETF MYNEWFUN) and '(SETF MYNEWFUN) are permitted
170 ;; as the object to use in the USE-VALUE restart.
171 (setq name
(restart-case (if (legal-fun-name-p name
)
172 (error 'undefined-function
:name name
)
173 (legal-fun-name-or-type-error name
))
175 :report
(lambda (stream)
176 (format stream
"Retry using ~s." name
))
179 :report
(lambda (stream)
180 (format stream
"Use specified function"))
181 :interactive read-evaluated-form
182 (if (functionp value
)
183 (return-from %coerce-name-to-fun value
)
185 (%coerce-name-to-fun name
))
187 ;; Coerce CALLABLE (a function-designator) to a FUNCTION.
188 ;; The compiler emits this when someone tries to FUNCALL something.
189 ;; Extended-function-designators are not accepted,
190 ;; This function declares EXPLICIT-CHECK, and we avoid calling
191 ;; SYMBOL-FUNCTION because that would do another check.
192 ;; It would be great if this could change its error message
193 ;; depending on the input to either:
194 ;; "foo is not a function designator" if not a CALLABLE
195 ;; "foo does not designate a currently defined function"
196 ;; if a symbol does not satisfy FBOUNDP.
197 (defun %coerce-callable-to-fun
(callable)
198 (declare (explicit-check))
201 (return-from %coerce-callable-to-fun callable
))
202 ((and symbol
(not null
)) ; NIL can't be fboundp. Quicker test this way.
203 (let ((fun (%symbol-function callable
)))
204 (when (and fun
(not (macro/special-guard-fun-p fun
)))
205 (return-from %coerce-callable-to-fun fun
))))
206 ;; If NIL, it's not technically a type-error, so instead hit the error
207 ;; in %coerce-name-to-fun which has a restart.
209 (t (error 'type-error
:expected-type
'(or symbol function
) :datum callable
)))
210 (%coerce-name-to-fun callable
))
212 ;;; Behaves just like %COERCE-CALLABLE-TO-FUN but has an ir2-convert optimizer.
213 (setf (symbol-function '%coerce-callable-for-call
) (symbol-function '%coerce-callable-to-fun
))
216 ;;;; definition encapsulation
218 (defstruct (encapsulation-info (:constructor make-encapsulation-info
221 ;; This is definition's encapsulation type. The encapsulated
222 ;; definition is in the previous ENCAPSULATION-INFO element or
223 ;; installed as the global definition of some function name.
225 ;; the previous, encapsulated definition. This used to be installed
226 ;; as a global definition for some function name, but it was
227 ;; replaced by an encapsulation of type TYPE.
228 (definition nil
:type function
))
229 (declaim (freeze-type encapsulation-info
))
231 ;;; Find the encapsulation info that has been closed over.
232 (defun encapsulation-info (fun)
233 (truly-the (or encapsulation-info null
)
235 (find-if-in-closure #'encapsulation-info-p fun
))))
237 (flet ((name->fun
(name)
239 (symbol (%symbol-function name
))
240 (t (binding* ((fdefn (find-fdefn name
) :exit-if-null
))
241 (fdefn-fun fdefn
))))))
243 ;;; Does NAME have an encapsulation of the given TYPE?
244 (defun encapsulated-p (name type
)
245 (let ((fun (name->fun name
)))
246 (when (typep fun
'generic-function
)
247 (return-from encapsulated-p
(encapsulated-generic-function-p fun type
)))
248 (do ((encap-info (encapsulation-info fun
)
250 (encapsulation-info-definition encap-info
))))
251 ((null encap-info
) nil
)
252 (declare (type (or encapsulation-info null
) encap-info
))
253 (when (eq (encapsulation-info-type encap-info
) type
)
256 ;;; Replace the definition of NAME with a function that calls FUNCTION
257 ;;; with the original function and its arguments.
258 ;;; TYPE is whatever you would like to associate with this
259 ;;; encapsulation for identification in case you need multiple
260 ;;; encapsulations of the same name.
261 (defun encapsulate (name type function
)
262 (let ((underlying-fun (name->fun name
)))
263 (when (macro/special-guard-fun-p underlying-fun
)
264 (error "~S can not be encapsulated" name
))
265 (if (typep underlying-fun
'generic-function
)
266 (encapsulate-generic-function underlying-fun type function
)
267 ;; We must bind and close over INFO. Consider the case where we
268 ;; encapsulate (the second) an encapsulated (the first)
269 ;; definition, and later someone unencapsulates the encapsulated
270 ;; (first) definition. We don't want our encapsulation (second) to
271 ;; bind basic-definition to the encapsulated (first) definition
272 ;; when it no longer exists. When unencapsulating, we make sure to
273 ;; clobber the appropriate INFO structure to allow
274 ;; basic-definition to be bound to the next definition instead of
275 ;; an encapsulation that no longer exists.
276 (let ((info (make-encapsulation-info type underlying-fun
)))
277 (setf (fdefn-fun (find-fdefn name
))
278 (named-lambda encapsulation
(&rest args
)
279 (apply function
(encapsulation-info-definition info
)
282 ;;; When removing an encapsulation, we must remember that
283 ;;; encapsulating definitions close over a reference to the
284 ;;; ENCAPSULATION-INFO that describes the encapsulating definition.
285 ;;; When you find an info with the target type, the previous info in
286 ;;; the chain has the ensulating definition of that type. We take the
287 ;;; encapsulated definition from the info with the target type, and we
288 ;;; store it in the previous info structure whose encapsulating
289 ;;; definition it describes looks to this previous info structure for
290 ;;; a definition to bind (see ENCAPSULATE). When removing the first
291 ;;; info structure, we do something conceptually equal, but
292 ;;; mechanically it is different.
293 (defun unencapsulate (name type
)
294 "Removes NAME's outermost encapsulation of the specified TYPE."
295 (let* ((fun (name->fun name
))
296 (encap-info (encapsulation-info fun
)))
297 (cond ((typep fun
'generic-function
)
298 (unencapsulate-generic-function fun type
))
300 ;; It disappeared on us, so don't worry about it.
302 ((eq (encapsulation-info-type encap-info
) type
)
303 ;; It's the first one, so change the fdefn object.
304 (setf (fdefn-fun (find-fdefn name
))
305 (encapsulation-info-definition encap-info
)))
307 ;; It must be an interior one, so find it.
309 (let ((next-info (encapsulation-info
310 (encapsulation-info-definition encap-info
))))
312 ;; Not there, so don't worry about it.
314 (when (eq (encapsulation-info-type next-info
) type
)
315 ;; This is it, so unlink us.
316 (setf (encapsulation-info-definition encap-info
)
317 (encapsulation-info-definition next-info
))
319 (setf encap-info next-info
))))))
325 ;;; KLUDGE: Er, it looks as though this means that
326 ;;; (FUNCALL (FDEFINITION 'FOO))
327 ;;; doesn't do the same thing as
329 ;;; and (SYMBOL-FUNCTION 'FOO) isn't in general the same thing
330 ;;; as (FDEFINITION 'FOO). That doesn't look like ANSI behavior to me.
331 ;;; Look e.g. at the ANSI definition of TRACE: "Whenever a traced
332 ;;; function is invoked, information about the call, ..". Try this:
333 ;;; (DEFUN FOO () (PRINT "foo"))
336 ;;; (FUNCALL (FDEFINITION 'FOO))
337 ;;; What to do? ANSI says TRACE "Might change the definitions of the
338 ;;; functions named by function-names." Might it be OK to just get
339 ;;; punt all this encapsulation stuff and go back to a simple but
340 ;;; correct implementation of TRACE? We'd lose the ability to redefine
341 ;;; a TRACEd function and keep the trace in place, but that seems
342 ;;; tolerable to me. (Is the wrapper stuff needed for anything else
345 ;;; The only problem I can see with not having a wrapper: If tracing
346 ;;; EQ, EQL, EQUAL, or EQUALP causes its function address to change,
347 ;;; it will mess up the MAKE-HASH-TABLE logic which uses EQ tests
348 ;;; on those function values. But given the ANSI statement about
349 ;;; TRACE causing things to change, that doesn't seem too unreasonable;
350 ;;; and we might even be able to forbid tracing these functions.
351 ;;; -- WHN 2001-11-02
352 (defun fdefinition (name)
353 "Return name's global function definition taking care to respect any
354 encapsulations and to return the innermost encapsulated definition.
356 (declare (explicit-check))
357 ;; %COERCE-NAME-TO-FUN signals an error for macros and special operators,
358 ;; but FDEFINITION should not, so pick off symbols using %SYMBOL-FUNCTION.
359 (strip-encapsulation (or (and (symbolp name
) (%symbol-function name
))
360 (%coerce-name-to-fun name
))))
361 (defun strip-encapsulation (fun)
363 (let ((encap-info (encapsulation-info fun
)))
365 (setf fun
(encapsulation-info-definition encap-info
))
368 (define-load-time-global *setf-fdefinition-hook
* nil
369 "A list of functions that (SETF FDEFINITION) invokes before storing the
370 new value. The functions take the function name and the new value.")
372 ;; Reject any "object of implementation-dependent nature" that
373 ;; so happens to be a function in SBCL, but which must not be
374 ;; bound to a function-name by way of (SETF FEDFINITION).
375 (defun err-if-unacceptable-function (object setter
)
376 (when (macro/special-guard-fun-p object
)
377 (error 'simple-reference-error
378 :references
'((:ansi-cl
:function fdefinition
))
379 :format-control
"~S is not acceptable to ~S."
380 :format-arguments
(list object setter
))))
382 (defun (setf fdefinition
) (new-value name
)
383 "Set NAME's global function definition."
384 (declare (type function new-value
) (optimize (safety 1)))
385 (declare (explicit-check))
386 (err-if-unacceptable-function new-value
'(setf fdefinition
))
387 (setq new-value
(strip-encapsulation new-value
))
388 (with-single-package-locked-error (:symbol name
"setting fdefinition of ~A")
389 (maybe-clobber-ftype name new-value
)
391 ;; Check for hash-table stuff. Woe onto him that mixes encapsulation
394 (let ((old (%symbol-function name
)))
395 (dolist (spec *user-hash-table-tests
*)
396 (cond ((eq old
(second spec
))
398 (setf (second spec
) new-value
))
399 ((eq old
(third spec
))
401 (setf (third spec
) new-value
))))))
403 (let ((fdefn (find-or-create-fdefn name
)))
404 (dolist (f *setf-fdefinition-hook
*)
405 (declare (type function f
))
406 (funcall f name new-value
))
407 (let ((encap-info (encapsulation-info (fdefn-fun fdefn
))))
412 (encapsulation-info-definition encap-info
))))
414 (setf encap-info more-info
)
415 (return (setf (encapsulation-info-definition encap-info
)
418 (setf (fdefn-fun fdefn
) new-value
)))))))
420 ;;;; FBOUNDP and FMAKUNBOUND
422 (defun fboundp (name)
423 "Return true if name has a global function definition."
424 (declare (explicit-check))
425 (awhen (find-fdefn name
) (fdefn-fun it
)))
427 (defun fmakunbound (name)
428 "Make NAME have no global function definition."
429 (declare (explicit-check))
430 (with-single-package-locked-error
431 (:symbol name
"removing the function or macro definition of ~A")
432 (let ((fdefn (find-fdefn name
)))
434 (undo-static-linkage fdefn
)
435 (fdefn-makunbound fdefn
)))
436 (undefine-fun-name name
)
439 ;;; A simple open-addressing hashset.
440 (define-load-time-global *fdefns
*
441 (cons (make-array 128 :initial-element
0) 0))
442 (define-load-time-global *fdefns-lock
* (sb-thread:make-mutex
:name
"fdefns"))
444 ;;; Fancily named fdefns are not attached to symbols, but instead in a custom
445 ;;; data structure which we probe in the manner of a quadratic probing hash-table.
446 ;;; A max load factor ensures that probing terminates.
447 ;;; https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/
448 ;;; contains a proof that triangular numbers mod 2^N visit every cell.
450 ;;; The intent here - which may be impossible to realize - was to allow garbage-collection
451 ;;; of FDEFNs whose name is not reachable. I couldn't get it to do the right thing.
452 ;;; e.g. (defmethod foo (x (y cons)) ...) creates mappings:
453 ;;; (SB-PCL::FAST-METHOD FOO (T CONS)) -> #<SB-KERNEL:FDEFN (SB-PCL::FAST-METHOD FOO (T CONS))>
454 ;;; (SB-PCL::SLOW-METHOD FOO (T CONS)) -> #<SB-KERNEL:FDEFN (SB-PCL::SLOW-METHOD FOO (T CONS))>
455 ;;; where it seems like (unintern 'FOO) should allow both of those to get GCd.
456 ;;; I suspect that it will require hanging those fancily named fdefns off the symbol
457 ;;; FOO rather than having a global table. Alternatively, that can be simulated by
458 ;;; having GC preserve liveness of any element whenever the second item in the list
459 ;;; comprising fdefn-name is an a-priori live symbol. That will be more efficient than
460 ;;; having a hash-table hanging off every symbol that names a method.
461 ;;; e.g. both of the preceding names would be hanging off of FOO, as would others
462 ;;; such as (FAST-METHOD FOO :AROUND (LIST INTEGER)) and a myriad of others.
463 ;;; I suspect that any approach of hanging off the symbols will be space-inefficient
464 ;;; and difficult to implement.
466 ;;; At any rate, we can make use of the key-in-value nature of fdefns to halve
467 ;;; the number of words required to store the name -> object mapping.
468 (defun get-fancily-named-fdefn (name constructor
&aux
(hash (globaldb-sxhashoid name
)))
469 (declare (type (or function null
) constructor
))
470 (labels ((lookup (vector &aux
(mask (1- (length vector
)))
471 (index (logand hash mask
))
474 ;; Because rehash is forced well before the table becomes 100% full,
475 ;; it should not be possible to loop infinitely here.
476 (loop (let ((fdefn (svref vector index
)))
477 (cond ((eql fdefn
0) ; not found
478 (return-from lookup
(or empty-cell index
)))
479 #+nil
((eql fdefn nil
) ; smashed by GC
480 (unless empty-cell
(setq empty-cell index
)))
481 ((equal (fdefn-name fdefn
) name
)
482 (return-from lookup fdefn
))))
483 (setq index
(logand (+ index
(incf step
)) mask
))))
484 (insert (hash item vector mask
&aux
(index (logand hash mask
))
487 (loop (case (svref vector index
)
489 (return (setf (svref vector
(or empty-cell index
)) item
)))
490 #+nil
((nil) ; smashed by GC
491 (unless empty-cell
(setq empty-cell index
))))
492 (setq index
(logand (+ index
(incf step
)) mask
)))))
493 (or (let ((result (lookup (car *fdefns
*))))
494 (when (fdefn-p result
) result
))
495 (when constructor
; double-check w/lock before inserting
496 (with-system-mutex (*fdefns-lock
*)
497 (let* ((fdefns *fdefns
*)
498 (vector (car fdefns
))
499 (result (lookup vector
)))
502 (let ((new-fdefn (funcall constructor name
)))
503 (if (<= (incf (cdr fdefns
)) (ash (length vector
) -
1)) ; under 50% full
504 ;; It might even be less full than that due to GC.
505 (setf (svref vector result
) new-fdefn
)
506 ;; The actual count is unknown without re-counting.
507 (let* ((count (count-if #'fdefn-p vector
))
508 (new-size (power-of-two-ceiling
509 (ceiling (* count
2))))
510 (new-vect (make-array new-size
:initial-element
0))
511 (new-mask (1- new-size
)))
512 (dovector (item vector
)
514 (insert (globaldb-sxhashoid (fdefn-name item
)) item
516 (insert hash new-fdefn new-vect new-mask
)
517 (setf *fdefns
* (cons new-vect
(1+ count
)))))