More fixes for cmucl host. Should be all good now.
[sbcl.git] / contrib / sb-introspect / introspect.lisp
blobc2d3617a65ba51ac878cbbbee18ab7286954d2b0
1 ;;; introspection library
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 ;;; For the avoidance of doubt, the exported interface is the supported
13 ;;; interface. Anything else is internal, though you're welcome to argue a
14 ;;; case for exporting it.
16 ;;; If you steal the code from this file to cut and paste into your
17 ;;; own project, there will be much wailing and gnashing of teeth.
18 ;;; Your teeth. If need be, we'll kick them for you. This is a
19 ;;; contrib, we're allowed to look in internals. You're an
20 ;;; application programmer, and are not.
22 ;;; TODO
23 ;;; 1) structs don't have within-file location info. problem for the
24 ;;; structure itself, accessors, the copier and the predicate
25 ;;; 3) error handling. Signal random errors, or handle and resignal 'our'
26 ;;; error, or return NIL?
27 ;;; 4) FIXMEs
29 (defpackage :sb-introspect
30 (:use "CL")
31 (:export "ALLOCATION-INFORMATION"
32 "FUNCTION-ARGLIST"
33 "FUNCTION-LAMBDA-LIST"
34 "FUNCTION-TYPE"
35 "DEFTYPE-LAMBDA-LIST"
36 "VALID-FUNCTION-NAME-P"
37 "FIND-DEFINITION-SOURCE"
38 "FIND-DEFINITION-SOURCES-BY-NAME"
39 "DEFINITION-SOURCE"
40 "DEFINITION-SOURCE-PATHNAME"
41 "DEFINITION-SOURCE-FORM-PATH"
42 "DEFINITION-SOURCE-FORM-NUMBER"
43 "DEFINITION-SOURCE-CHARACTER-OFFSET"
44 "DEFINITION-SOURCE-FILE-WRITE-DATE"
45 "DEFINITION-SOURCE-PLIST"
46 "FIND-FUNCTION-CALLEES"
47 "FIND-FUNCTION-CALLERS"
48 "MAP-ROOT"
49 "WHO-BINDS"
50 "WHO-CALLS"
51 "WHO-REFERENCES"
52 "WHO-SETS"
53 "WHO-MACROEXPANDS"
54 "WHO-SPECIALIZES-DIRECTLY"
55 "WHO-SPECIALIZES-GENERALLY"))
57 (in-package :sb-introspect)
59 ;;;; Internal interface for SBCL debug info
61 ;;; Here are some tutorial-style type definitions to help understand
62 ;;; the internal SBCL debugging data structures we're using. The
63 ;;; commentary is based on CMUCL's debug internals manual.
64 ;;;
65 (deftype debug-info ()
66 "Structure containing all the debug information related to a function.
67 Function objects reference debug-infos which in turn reference
68 debug-sources and so on."
69 'sb-c::compiled-debug-info)
71 (deftype debug-source ()
72 "Debug sources describe where to find source code.
73 For example, the debug source for a function compiled from a file will
74 include the pathname of the file and the position of the definition."
75 'sb-c::debug-source)
77 (deftype debug-function ()
78 "Debug function represent static compile-time information about a function."
79 'sb-c::compiled-debug-fun)
81 (declaim (ftype (sb-int:sfunction (function) debug-info) function-debug-info))
82 (defun function-debug-info (function)
83 (let* ((function-object (sb-kernel::%fun-fun function))
84 (function-header (sb-kernel:fun-code-header function-object)))
85 (sb-kernel:%code-debug-info function-header)))
87 (declaim (ftype (sb-int:sfunction (function) debug-source) function-debug-source))
88 (defun function-debug-source (function)
89 (debug-info-source (function-debug-info function)))
91 (declaim (ftype (sb-int:sfunction (debug-info) debug-source) debug-info-source))
92 (defun debug-info-source (debug-info)
93 (sb-c::debug-info-source debug-info))
95 (declaim (ftype (sb-int:sfunction (t debug-info) debug-function) debug-info-debug-function))
96 (defun debug-info-debug-function (function debug-info)
97 (let ((map (sb-c::compiled-debug-info-fun-map debug-info))
98 (name (sb-kernel:%simple-fun-name (sb-kernel:%fun-fun function))))
99 (or
100 (find-if
101 (lambda (x)
102 (and
103 (sb-c::compiled-debug-fun-p x)
104 (eq (sb-c::compiled-debug-fun-name x) name)))
105 map)
106 (elt map 0))))
108 (defun valid-function-name-p (name)
109 "True if NAME denotes a valid function name, ie. one that can be passed to
110 FBOUNDP."
111 (and (sb-int:valid-function-name-p name) t))
113 ;;;; Utilities for code
115 (declaim (inline map-code-constants))
116 (defun map-code-constants (code fn)
117 "Call FN for each constant in CODE's constant pool."
118 (check-type code sb-kernel:code-component)
119 (loop for i from sb-vm:code-constants-offset below
120 (sb-kernel:get-header-data code)
121 do (funcall fn (sb-kernel:code-header-ref code i))))
123 (declaim (inline map-allocated-code-components))
124 (defun map-allocated-code-components (spaces fn)
125 "Call FN for each allocated code component in one of SPACES. FN
126 receives the object and its size as arguments. SPACES should be a
127 list of the symbols :dynamic, :static, or :read-only."
128 (dolist (space spaces)
129 (sb-vm::map-allocated-objects
130 (lambda (obj header size)
131 (when (= sb-vm:code-header-widetag header)
132 (funcall fn obj size)))
133 space)))
135 (declaim (inline map-caller-code-components))
136 (defun map-caller-code-components (function spaces fn)
137 "Call FN for each code component with a fdefn for FUNCTION in its
138 constant pool."
139 (let ((function (coerce function 'function)))
140 (map-allocated-code-components
141 spaces
142 (lambda (obj size)
143 (declare (ignore size))
144 (map-code-constants
146 (lambda (constant)
147 (when (and (sb-kernel:fdefn-p constant)
148 (eq (sb-kernel:fdefn-fun constant)
149 function))
150 (funcall fn obj))))))))
152 ;;;; Finding definitions
154 (defstruct definition-source
155 ;; Pathname of the source file that the definition was compiled from.
156 ;; This is null if the definition was not compiled from a file.
157 (pathname nil :type (or null pathname))
158 ;; Source-path of the definition within the file.
159 ;; This may be incomplete depending on the debug level at which the
160 ;; source was compiled.
161 (form-path '() :type list)
162 ;; Depth first number of the form.
163 ;; FORM-PATH above usually contains just the top-level form number,
164 ;; ideally the proper form path could be dervied from the
165 ;; form-number and the tlf-number, but it's a bit complicated and
166 ;; Slime already knows how to deal with form numbers, so delegate
167 ;; that job to Slime.
168 (form-number nil :type (or null unsigned-byte))
169 ;; Character offset of the top-level-form containing the definition.
170 ;; This corresponds to the first element of form-path.
171 (character-offset nil :type (or null unsigned-byte))
172 ;; File-write-date of the source file when compiled.
173 ;; Null if not compiled from a file.
174 (file-write-date nil :type (or null unsigned-byte))
175 ;; plist from WITH-COMPILATION-UNIT
176 (plist nil)
177 ;; Any extra metadata that the caller might be interested in. For
178 ;; example the specializers of the method whose definition-source this
179 ;; is.
180 (description nil :type list))
182 (defun vop-sources-from-fun-templates (name)
183 (let ((fun-info (sb-int:info :function :info name)))
184 (when fun-info
185 (loop for vop in (sb-c::fun-info-templates fun-info)
186 for source = (find-definition-source
187 (sb-c::vop-info-generator-function vop))
188 do (setf (definition-source-description source)
189 (if (sb-c::template-note vop)
190 (list (sb-c::template-name vop)
191 (sb-c::template-note vop))
192 (list (sb-c::template-name vop))))
193 collect source))))
195 (defun find-vop-source (name)
196 (let* ((templates (vop-sources-from-fun-templates name))
197 (vop (gethash name sb-c::*backend-template-names*))
198 (generator (when vop
199 (sb-c::vop-info-generator-function vop)))
200 (source (when generator
201 (find-definition-source generator))))
202 (cond
203 (source
204 (setf (definition-source-description source)
205 (list name))
206 (cons source templates))
208 templates))))
210 (defun find-definition-sources-by-name (name type)
211 "Returns a list of DEFINITION-SOURCEs for the objects of type TYPE
212 defined with name NAME. NAME may be a symbol or a extended function
213 name. Type can currently be one of the following:
215 (Public)
216 :CLASS
217 :COMPILER-MACRO
218 :CONDITION
219 :CONSTANT
220 :FUNCTION
221 :GENERIC-FUNCTION
222 :MACRO
223 :METHOD
224 :METHOD-COMBINATION
225 :PACKAGE
226 :SETF-EXPANDER
227 :STRUCTURE
228 :SYMBOL-MACRO
229 :TYPE
230 :ALIEN-TYPE
231 :VARIABLE
232 :DECLARATION
234 (Internal)
235 :OPTIMIZER
236 :SOURCE-TRANSFORM
237 :TRANSFORM
238 :VOP
239 :IR1-CONVERT
241 If an unsupported TYPE is requested, the function will return NIL.
243 (flet ((get-class (name)
244 (and (symbolp name)
245 (find-class name nil)))
246 (real-fdefinition (name)
247 ;; for getting the real function object, even if the
248 ;; function is being profiled
249 (let ((profile-info (gethash name sb-profile::*profiled-fun-name->info*)))
250 (if profile-info
251 (sb-profile::profile-info-encapsulated-fun profile-info)
252 (fdefinition name)))))
253 (sb-int:ensure-list
254 (case type
255 ((:variable)
256 (when (and (symbolp name)
257 (member (sb-int:info :variable :kind name)
258 '(:global :special :alien)))
259 (translate-source-location (sb-int:info :source-location type name))))
260 ((:constant)
261 (when (and (symbolp name)
262 (eq (sb-int:info :variable :kind name) :constant))
263 (translate-source-location (sb-int:info :source-location type name))))
264 ((:symbol-macro)
265 (when (and (symbolp name)
266 (eq (sb-int:info :variable :kind name) :macro))
267 (translate-source-location (sb-int:info :source-location type name))))
268 ((:macro)
269 (when (and (symbolp name)
270 (macro-function name))
271 (find-definition-source (macro-function name))))
272 ((:compiler-macro)
273 (when (compiler-macro-function name)
274 (find-definition-source (compiler-macro-function name))))
275 (:ir1-convert
276 (let ((converter (sb-int:info :function :ir1-convert name)))
277 (and converter
278 (find-definition-source converter))))
279 ((:function :generic-function)
280 (when (and (fboundp name)
281 (or (consp name)
282 (and
283 (not (macro-function name))
284 (not (special-operator-p name)))))
285 (let ((fun (real-fdefinition name)))
286 (when (eq (not (typep fun 'generic-function))
287 (not (eq type :generic-function)))
288 (find-definition-source fun)))))
289 ((:type)
290 ;; Source locations for types are saved separately when the expander
291 ;; is a closure without a good source-location.
292 (let ((loc (sb-int:info :type :source-location name)))
293 (if loc
294 (translate-source-location loc)
295 (let ((expander-fun (sb-int:info :type :expander name)))
296 (when (functionp expander-fun)
297 (find-definition-source expander-fun))))))
298 ((:method)
299 (when (fboundp name)
300 (let ((fun (real-fdefinition name)))
301 (when (typep fun 'generic-function)
302 (loop for method in (sb-mop::generic-function-methods
303 fun)
304 for source = (find-definition-source method)
305 when source collect source)))))
306 ((:setf-expander)
307 (when (and (consp name)
308 (eq (car name) 'setf))
309 (setf name (cadr name)))
310 (let ((expander (sb-int:info :setf :expander name)))
311 (when expander
312 (find-definition-source
313 (cond ((symbolp expander) (symbol-function expander))
314 ((listp expander) (cdr expander))
315 (t expander))))))
316 ((:structure)
317 (let ((class (get-class name)))
318 (if class
319 (when (typep class 'sb-pcl::structure-class)
320 (find-definition-source class))
321 (when (sb-int:info :typed-structure :info name)
322 (translate-source-location
323 (sb-int:info :source-location :typed-structure name))))))
324 ((:condition :class)
325 (let ((class (get-class name)))
326 (when (and class
327 (not (typep class 'sb-pcl::structure-class)))
328 (when (eq (not (typep class 'sb-pcl::condition-class))
329 (not (eq type :condition)))
330 (find-definition-source class)))))
331 ((:method-combination)
332 (let ((combination-fun
333 (find-method #'sb-mop:find-method-combination
335 (list (find-class 'generic-function)
336 (list 'eql name)
338 nil)))
339 (when combination-fun
340 (find-definition-source combination-fun))))
341 ((:package)
342 (when (symbolp name)
343 (let ((package (find-package name)))
344 (when package
345 (find-definition-source package)))))
346 ;; TRANSFORM and OPTIMIZER handling from swank-sbcl
347 ((:transform)
348 (when (symbolp name)
349 (let ((fun-info (sb-int:info :function :info name)))
350 (when fun-info
351 (loop for xform in (sb-c::fun-info-transforms fun-info)
352 for source = (find-definition-source
353 (sb-c::transform-function xform))
354 for typespec = (sb-kernel:type-specifier
355 (sb-c::transform-type xform))
356 for note = (sb-c::transform-note xform)
357 do (setf (definition-source-description source)
358 (if (consp typespec)
359 (list (second typespec) note)
360 (list note)))
361 collect source)))))
362 ((:optimizer)
363 (let ((fun-info (and (symbolp name)
364 (sb-int:info :function :info name))))
365 (when fun-info
366 (let ((otypes '((sb-c:fun-info-derive-type . sb-c:derive-type)
367 (sb-c:fun-info-ltn-annotate . sb-c:ltn-annotate)
368 (sb-c:fun-info-optimizer . sb-c:optimizer)
369 (sb-c:fun-info-ir2-convert . sb-c:ir2-convert)
370 (sb-c::fun-info-stack-allocate-result
371 . sb-c::stack-allocate-result))))
372 (loop for (reader . name) in otypes
373 for fn = (funcall reader fun-info)
374 when fn collect
375 (let ((source (find-definition-source fn)))
376 (setf (definition-source-description source)
377 (list name))
378 source))))))
379 (:vop
380 (let ((loc (sb-int:info :source-location type name)))
381 (if loc
382 (translate-source-location loc)
383 (find-vop-source name))))
384 (:alien-type
385 (let ((loc (sb-int:info :source-location type name)))
386 (and loc
387 (translate-source-location loc))))
388 ((:source-transform)
389 (let* ((transform-fun
390 (or (sb-int:info :function :source-transform name)
391 (and (typep name '(cons (eql setf) (cons symbol null)))
392 (sb-int:info :function :source-transform
393 (second name)))))
394 ;; A cons for the :source-transform is essentially the same
395 ;; info that was formerly in :structure-accessor.
396 (accessor (and (consp transform-fun) (cdr transform-fun))))
397 ;; Structure accessors have source transforms, but the
398 ;; returned locations will neither show the actual place
399 ;; where it's defined, nor is really interesting.
400 (when (and transform-fun
401 (not accessor))
402 (find-definition-source transform-fun))))
403 (:declaration
404 (let ((locations (sb-int:info :source-location :declaration name)))
405 (loop for (kind loc) on locations by #'cddr
406 when loc
407 collect (let ((loc (translate-source-location loc)))
408 (setf (definition-source-description loc)
409 ;; Copy list to ensure that user code
410 ;; cannot mutate the original.
411 (copy-list (sb-int:ensure-list kind)))
412 loc))))
414 nil)))))
416 (defun find-definition-source (object)
417 (typecase object
418 ((or sb-pcl::condition-class sb-pcl::structure-class)
419 (let ((classoid (sb-impl::find-classoid (class-name object))))
420 (when classoid
421 (let ((layout (sb-impl::classoid-layout classoid)))
422 (when layout
423 (translate-source-location
424 (sb-kernel::layout-source-location layout)))))))
425 (method-combination
426 (car
427 (find-definition-sources-by-name
428 (sb-pcl::method-combination-type-name object) :method-combination)))
429 (package
430 (translate-source-location (sb-impl::package-source-location object)))
431 ((or class sb-mop:slot-definition)
432 (translate-source-location (sb-pcl::definition-source object)))
433 ;; Use the PCL definition location information instead of the function
434 ;; debug-info for methods and generic functions. Sometimes the
435 ;; debug-info would point into PCL internals instead of the proper
436 ;; location.
437 (generic-function
438 (let ((source (translate-source-location
439 (sb-pcl::definition-source object))))
440 (when source
441 (setf (definition-source-description source)
442 (list (sb-mop:generic-function-lambda-list object))))
443 source))
444 (method
445 (let ((source (translate-source-location
446 (sb-pcl::definition-source object))))
447 (when source
448 (setf (definition-source-description source)
449 (append (method-qualifiers object)
450 (if (sb-mop:method-generic-function object)
451 (sb-pcl::unparse-specializers
452 (sb-mop:method-generic-function object)
453 (sb-mop:method-specializers object))
454 (sb-mop:method-specializers object)))))
455 source))
456 #+sb-eval
457 (sb-eval:interpreted-function
458 (let ((source (translate-source-location
459 (sb-eval:interpreted-function-source-location object))))
460 source))
461 #+sb-fasteval
462 (sb-interpreter:interpreted-function
463 (translate-source-location (sb-interpreter:fun-source-location object)))
464 (function
465 (find-function-definition-source object))
466 ((or condition standard-object structure-object)
467 (find-definition-source (class-of object)))
469 (error "Don't know how to retrieve source location for a ~S"
470 (type-of object)))))
472 (defun find-function-definition-source (function)
473 (let* ((debug-info (function-debug-info function))
474 (debug-source (debug-info-source debug-info))
475 (debug-fun (debug-info-debug-function function debug-info))
476 (tlf (if debug-fun (sb-c::compiled-debug-fun-tlf-number debug-fun))))
477 (make-definition-source
478 :pathname
479 (when (stringp (sb-c::debug-source-namestring debug-source))
480 (parse-namestring (sb-c::debug-source-namestring debug-source)))
481 :character-offset
482 (if tlf
483 (elt (sb-c::debug-source-start-positions debug-source) tlf))
484 :form-path (if tlf (list tlf))
485 :form-number (sb-c::compiled-debug-fun-form-number debug-fun)
486 :file-write-date (sb-c::debug-source-created debug-source)
487 :plist (sb-c::debug-source-plist debug-source))))
489 (defun translate-source-location (location)
490 (if location
491 (make-definition-source
492 :pathname (let ((n (sb-c:definition-source-location-namestring location)))
493 (when n
494 (parse-namestring n)))
495 :form-path
496 (let ((number (sb-c:definition-source-location-toplevel-form-number
497 location)))
498 (when number
499 (list number)))
500 :form-number (sb-c:definition-source-location-form-number
501 location)
502 :plist (sb-c:definition-source-location-plist location))
503 (make-definition-source)))
505 (sb-int:define-deprecated-function :late "1.0.24.5" function-arglist function-lambda-list
506 (function)
507 (function-lambda-list function))
509 (defun function-lambda-list (function)
510 "Describe the lambda list for the extended function designator FUNCTION.
511 Works for special-operators, macros, simple functions, interpreted functions,
512 and generic functions. Signals an error if FUNCTION is not a valid extended
513 function designator."
514 ;; FIXME: sink this logic into SB-KERNEL:%FUN-LAMBDA-LIST and just call that?
515 (cond ((and (symbolp function) (special-operator-p function))
516 (function-lambda-list (sb-int:info :function :ir1-convert function)))
517 ((valid-function-name-p function)
518 (function-lambda-list (or (and (symbolp function)
519 (macro-function function))
520 (fdefinition function))))
521 ((typep function 'generic-function)
522 (sb-pcl::generic-function-pretty-arglist function))
524 (sb-kernel:%fun-lambda-list function))))
526 (defun deftype-lambda-list (typespec-operator)
527 "Returns the lambda list of TYPESPEC-OPERATOR as first return
528 value, and a flag whether the arglist could be found as second
529 value."
530 (check-type typespec-operator symbol)
531 ;; Don't return a lambda-list for combinators AND,OR,NOT.
532 (let* ((f (and (sb-int:info :type :kind typespec-operator)
533 (sb-int:info :type :expander typespec-operator)))
534 (f (if (listp f) (car f) f)))
535 (if (functionp f)
536 (values (sb-kernel:%fun-lambda-list f) t)
537 (values nil nil))))
539 (defun function-type (function-designator)
540 "Returns the ftype of FUNCTION-DESIGNATOR, or NIL."
541 (flet ((ftype-of (function-designator)
542 (sb-kernel:type-specifier
543 (sb-int:proclaimed-ftype function-designator))))
544 (etypecase function-designator
545 (symbol
546 (when (and (fboundp function-designator)
547 (not (macro-function function-designator))
548 (not (special-operator-p function-designator)))
549 (ftype-of function-designator)))
550 (cons
551 (when (and (sb-int:legal-fun-name-p function-designator)
552 (fboundp function-designator))
553 (ftype-of function-designator)))
554 (generic-function
555 (function-type (sb-pcl:generic-function-name function-designator)))
556 (function
557 ;; Give declared type in globaldb priority over derived type
558 ;; because it contains more accurate information e.g. for
559 ;; struct-accessors.
560 (let ((type (function-type (sb-kernel:%fun-name
561 (sb-impl::%fun-fun function-designator)))))
562 (if type
563 type
564 (sb-impl::%fun-type function-designator)))))))
566 ;;;; find callers/callees, liberated from Helmut Eller's code in SLIME
568 ;;; This interface is tremendously experimental.
570 ;;; For the moment I'm taking the view that FDEFN is an internal
571 ;;; object (one out of one CMUCL developer surveyed didn't know what
572 ;;; they were for), so these routines deal in FUNCTIONs
574 ;;; Find callers and callees by looking at the constant pool of
575 ;;; compiled code objects. We assume every fdefn object in the
576 ;;; constant pool corresponds to a call to that function. A better
577 ;;; strategy would be to use the disassembler to find actual
578 ;;; call-sites.
580 (defun find-function-callees (function)
581 "Return functions called by FUNCTION."
582 (declare (sb-kernel:simple-fun function))
583 (let ((callees '()))
584 (map-code-constants
585 (sb-kernel:fun-code-header function)
586 (lambda (obj)
587 (when (sb-kernel:fdefn-p obj)
588 (push (sb-kernel:fdefn-fun obj)
589 callees))))
590 callees))
592 (defun find-function-callers (function &optional (spaces '(:read-only :static
593 :dynamic)))
594 "Return functions which call FUNCTION, by searching SPACES for code objects"
595 (let ((referrers '()))
596 (map-caller-code-components
597 function
598 spaces
599 (lambda (code)
600 (let ((entry (sb-kernel:%code-entry-points code)))
601 (cond ((not entry)
602 (push (princ-to-string code) referrers))
604 (loop for e = entry then (sb-kernel::%simple-fun-next e)
605 while e
606 do (pushnew e referrers)))))))
607 referrers))
609 ;;; XREF facility
611 (defun get-simple-fun (functoid)
612 (etypecase functoid
613 (sb-kernel:fdefn
614 (get-simple-fun (sb-kernel:fdefn-fun functoid)))
615 ((or null sb-kernel:funcallable-instance)
616 nil)
617 (sb-kernel:closure
618 ;; FIXME: should use ENCAPSULATION-INFO instead of hardwiring an index.
619 (let ((fun (sb-kernel:%closure-fun functoid)))
620 (if (and (eq (sb-kernel:%fun-name fun) 'sb-impl::encapsulation)
621 (plusp (sb-kernel:get-closure-length functoid))
622 (typep (sb-kernel:%closure-index-ref functoid 0) 'sb-impl::encapsulation-info))
623 (get-simple-fun
624 (sb-impl::encapsulation-info-definition
625 (sb-kernel:%closure-index-ref functoid 0)))
626 fun)))
627 (function
628 (sb-kernel:%fun-fun functoid))))
630 ;; Call FUNCTION with two args, NAME and VALUE, for each value that is
631 ;; either the FDEFINITION or MACRO-FUNCTION of some global name.
633 (defun call-with-each-global-functoid (function)
634 (sb-c::call-with-each-globaldb-name
635 (lambda (name)
636 ;; In general it might be unsafe to call INFO with a NAME that is not
637 ;; valid for the kind of info being retrieved, as when the defaulting
638 ;; function tries to perform a sanity-check. But here it's safe.
639 (let ((functoid (or (sb-int:info :function :macro-function name)
640 (sb-int:info :function :definition name))))
641 (if functoid
642 (funcall function name functoid))))))
644 (defun collect-xref (kind-index wanted-name)
645 (let ((ret nil))
646 (flet ((process (info-name value)
647 ;; Get a simple-fun for the definition, and an xref array
648 ;; from the table if available.
649 (let* ((simple-fun (get-simple-fun value))
650 (xrefs (when simple-fun
651 (sb-kernel:%simple-fun-xrefs simple-fun)))
652 (array (when xrefs
653 (aref xrefs kind-index))))
654 ;; Loop through the name/path xref entries in the table
655 (loop for i from 0 below (length array) by 2
656 for xref-name = (aref array i)
657 for xref-form-number = (aref array (+ i 1))
658 do (when (equal xref-name wanted-name)
659 (let ((source-location
660 (find-function-definition-source simple-fun)))
661 ;; Use the more accurate source path from
662 ;; the xref entry.
663 (setf (definition-source-form-number source-location)
664 xref-form-number)
665 (push (cons info-name source-location)
666 ret)))))))
667 (call-with-each-global-functoid
668 (lambda (info-name value)
669 ;; Functions with EQL specializers no longer get a fdefinition,
670 ;; process all the methods from a generic function
671 (cond ((and (sb-kernel:fdefn-p value)
672 (typep (sb-kernel:fdefn-fun value) 'generic-function))
673 (loop for method in (sb-mop:generic-function-methods (sb-kernel:fdefn-fun value))
674 for fun = (sb-pcl::safe-method-fast-function method)
675 when fun
677 (process (sb-kernel:%fun-name fun) fun)))
678 ;; Methods are alredy processed above
679 ((and (sb-kernel:fdefn-p value)
680 (consp (sb-kernel:fdefn-name value))
681 (member (car (sb-kernel:fdefn-name value))
682 '(sb-pcl::slow-method sb-pcl::fast-method))))
684 (process info-name value))))))
685 ret))
687 (defun who-calls (function-name)
688 "Use the xref facility to search for source locations where the
689 global function named FUNCTION-NAME is called. Returns a list of
690 function name, definition-source pairs."
691 (collect-xref #.(position :calls sb-c::*xref-kinds*) function-name))
693 (defun who-binds (symbol)
694 "Use the xref facility to search for source locations where the
695 special variable SYMBOL is rebound. Returns a list of function name,
696 definition-source pairs."
697 (collect-xref #.(position :binds sb-c::*xref-kinds*) symbol))
699 (defun who-references (symbol)
700 "Use the xref facility to search for source locations where the
701 special variable or constant SYMBOL is read. Returns a list of function
702 name, definition-source pairs."
703 (collect-xref #.(position :references sb-c::*xref-kinds*) symbol))
705 (defun who-sets (symbol)
706 "Use the xref facility to search for source locations where the
707 special variable SYMBOL is written to. Returns a list of function name,
708 definition-source pairs."
709 (collect-xref #.(position :sets sb-c::*xref-kinds*) symbol))
711 (defun who-macroexpands (macro-name)
712 "Use the xref facility to search for source locations where the
713 macro MACRO-NAME is expanded. Returns a list of function name,
714 definition-source pairs."
715 (collect-xref #.(position :macroexpands sb-c::*xref-kinds*) macro-name))
717 (defun who-specializes-directly (class-designator)
718 "Search for source locations of methods directly specializing on
719 CLASS-DESIGNATOR. Returns an alist of method name, definition-source
720 pairs.
722 A method matches the criterion either if it specializes on the same
723 class as CLASS-DESIGNATOR designates (this includes CLASS-EQ
724 specializers), or if it eql-specializes on an instance of the
725 designated class.
727 Experimental.
729 (let ((class (canonicalize-class-designator class-designator)))
730 (unless class
731 (return-from who-specializes-directly nil))
732 (let ((result (collect-specializing-methods
733 #'(lambda (specl)
734 ;; Does SPECL specialize on CLASS directly?
735 (typecase specl
736 (sb-pcl::class-eq-specializer
737 (eq (sb-pcl::specializer-object specl) class))
738 (sb-pcl::eql-specializer
739 (let ((obj (sb-mop:eql-specializer-object specl)))
740 (eq (class-of obj) class)))
741 ((not sb-pcl::standard-specializer)
742 nil)
744 (eq specl class)))))))
745 (map-into result #'(lambda (m)
746 (cons `(method ,(method-generic-function-name m))
747 (find-definition-source m)))
748 result))))
750 (defun who-specializes-generally (class-designator)
751 "Search for source locations of methods specializing on
752 CLASS-DESIGNATOR, or a subclass of it. Returns an alist of method
753 name, definition-source pairs.
755 A method matches the criterion either if it specializes on the
756 designated class itself or a subclass of it (this includes CLASS-EQ
757 specializers), or if it eql-specializes on an instance of the
758 designated class or a subclass of it.
760 Experimental.
762 (let ((class (canonicalize-class-designator class-designator)))
763 (unless class
764 (return-from who-specializes-generally nil))
765 (let ((result (collect-specializing-methods
766 #'(lambda (specl)
767 ;; Does SPECL specialize on CLASS or a subclass
768 ;; of it?
769 (typecase specl
770 (sb-pcl::class-eq-specializer
771 (subtypep (sb-pcl::specializer-object specl) class))
772 (sb-pcl::eql-specializer
773 (typep (sb-mop:eql-specializer-object specl) class))
774 ((not sb-pcl::standard-specializer)
775 nil)
777 (subtypep specl class)))))))
778 (map-into result #'(lambda (m)
779 (cons `(method ,(method-generic-function-name m))
780 (find-definition-source m)))
781 result))))
783 (defun canonicalize-class-designator (class-designator)
784 (typecase class-designator
785 (symbol (find-class class-designator nil))
786 (class class-designator)
787 (t nil)))
789 (defun method-generic-function-name (method)
790 (sb-mop:generic-function-name (sb-mop:method-generic-function method)))
792 (defun collect-specializing-methods (predicate)
793 (let ((result '()))
794 (sb-pcl::map-specializers
795 #'(lambda (specl)
796 (when (funcall predicate specl)
797 (let ((methods (sb-mop:specializer-direct-methods specl)))
798 (setf result (append methods result))))))
799 (delete-duplicates result)))
802 ;;;; ALLOCATION INTROSPECTION
804 (defun allocation-information (object)
805 #+sb-doc
806 "Returns information about the allocation of OBJECT. Primary return value
807 indicates the general type of allocation: :IMMEDIATE, :HEAP, :STACK,
808 or :FOREIGN.
810 Possible secondary return value provides additional information about the
811 allocation.
813 For :HEAP objects the secondary value is a plist:
815 :SPACE
816 Indicates the heap segment the object is allocated in.
818 :GENERATION
819 Is the current generation of the object: 0 for nursery, 6 for pseudo-static
820 generation loaded from core. (GENCGC and :SPACE :DYNAMIC only.)
822 :LARGE
823 Indicates a \"large\" object subject to non-copying
824 promotion. (GENCGC and :SPACE :DYNAMIC only.)
826 :BOXED
827 Indicates that the object is allocated in a boxed region. Unboxed
828 allocation is used for eg. specialized arrays after they have survived one
829 collection. (GENCGC and :SPACE :DYNAMIC only.)
831 :PINNED
832 Indicates that the page(s) on which the object resides are kept live due
833 to conservative references. Note that object may reside on a pinned page
834 even if :PINNED in NIL if the GC has not had the need to mark the the page
835 as pinned. (GENCGC and :SPACE :DYNAMIC only.)
837 :WRITE-PROTECTED
838 Indicates that the page on which the object starts is write-protected,
839 which indicates for :BOXED objects that it hasn't been written to since
840 the last GC of its generation. (GENCGC and :SPACE :DYNAMIC only.)
842 :PAGE
843 The index of the page the object resides on. (GENGC and :SPACE :DYNAMIC
844 only.)
846 For :STACK objects secondary value is the thread on whose stack the object is
847 allocated.
849 Expected use-cases include introspection to gain insight into allocation and
850 GC behaviour and restricting memoization to heap-allocated arguments.
852 Experimental: interface subject to change."
853 ;; FIXME: Would be nice to provide the size of the object as well, though
854 ;; maybe that should be a separate function, and something like MAP-PARTS
855 ;; for mapping over parts of arbitrary objects so users can get "deep sizes"
856 ;; as well if they want to.
858 ;; FIXME: For the memoization use-case possibly we should also provide a
859 ;; simpler HEAP-ALLOCATED-P, since that doesn't require disabling the GC
860 ;; scanning threads for negative answers? Similarly, STACK-ALLOCATED-P for
861 ;; checking if an object has been stack-allocated by a given thread for
862 ;; testing purposes might not come amiss.
863 (if (typep object '(or fixnum character
864 #.(if (= sb-vm:n-word-bits 64) 'single-float (values))))
865 (values :immediate nil)
866 (let ((plist
867 (sb-sys:without-gcing
868 ;; Disable GC so the object cannot move to another page while
869 ;; we have the address.
870 (let* ((addr (sb-kernel:get-lisp-obj-address object))
871 (space
872 (cond ((< sb-vm:read-only-space-start addr
873 (ash sb-vm:*read-only-space-free-pointer*
874 sb-vm:n-fixnum-tag-bits))
875 :read-only)
876 ((< sb-vm:static-space-start addr
877 (ash sb-vm:*static-space-free-pointer*
878 sb-vm:n-fixnum-tag-bits))
879 :static)
880 ((< (sb-kernel:current-dynamic-space-start) addr
881 (sb-sys:sap-int (sb-kernel:dynamic-space-free-pointer)))
882 :dynamic))))
883 (when space
884 #+gencgc
885 (if (eq :dynamic space)
886 (let ((index (sb-vm::find-page-index addr)))
887 (symbol-macrolet ((page (sb-alien:deref sb-vm::page-table index)))
888 (let ((flags (sb-alien:slot page 'sb-vm::flags)))
889 (list :space space
890 :generation (sb-alien:slot page 'sb-vm::gen)
891 :write-protected (logbitp 0 flags)
892 :boxed (logbitp 2 flags)
893 :pinned (logbitp 5 flags)
894 :large (logbitp 6 flags)
895 :page index))))
896 (list :space space))
897 #-gencgc
898 (list :space space))))))
899 (cond (plist
900 (values :heap plist))
902 (let ((sap (sb-sys:int-sap (sb-kernel:get-lisp-obj-address object))))
903 ;; FIXME: Check other stacks as well.
904 #+sb-thread
905 (dolist (thread (sb-thread:list-all-threads))
906 (let ((c-start (sb-di::descriptor-sap
907 (sb-thread::%symbol-value-in-thread
908 'sb-vm:*control-stack-start*
909 thread)))
910 (c-end (sb-di::descriptor-sap
911 (sb-thread::%symbol-value-in-thread
912 'sb-vm:*control-stack-end*
913 thread))))
914 (when (and c-start c-end)
915 (when (and (sb-sys:sap<= c-start sap)
916 (sb-sys:sap< sap c-end))
917 (return-from allocation-information
918 (values :stack thread))))))
919 #-sb-thread
920 (when (sb-vm:control-stack-pointer-valid-p sap nil)
921 (return-from allocation-information
922 (values :stack sb-thread::*current-thread*))))
923 :foreign)))))
925 (defun map-root (function object &key simple (ext t))
926 "Call FUNCTION with all non-immediate objects pointed to by OBJECT.
927 Returns OBJECT.
929 If SIMPLE is true (default is NIL), elides those pointers that are not
930 notionally part of certain built-in objects, but backpointers to a
931 conceptual parent: eg. elides the pointer from a SYMBOL to the
932 corresponding PACKAGE.
934 If EXT is true (default is T), includes some pointers that are not
935 actually contained in the object, but found in certain well-known
936 indirect containers: FDEFINITIONs, EQL specializers, classes, and
937 thread-local symbol values in other threads fall into this category.
939 NOTE: calling MAP-ROOT with a THREAD does not currently map over
940 conservative roots from the thread registers and interrupt contexts.
942 Experimental: interface subject to change."
943 (let ((fun (coerce function 'function))
944 (seen (sb-int:alloc-xset)))
945 (flet ((call (part)
946 (when (and (member (sb-kernel:lowtag-of part)
947 `(,sb-vm:instance-pointer-lowtag
948 ,sb-vm:list-pointer-lowtag
949 ,sb-vm:fun-pointer-lowtag
950 ,sb-vm:other-pointer-lowtag))
951 (not (sb-int:xset-member-p part seen)))
952 (sb-int:add-to-xset part seen)
953 (funcall fun part))))
954 (when ext
955 (let ((table sb-pcl::*eql-specializer-table*))
956 (call (sb-int:with-locked-system-table (table)
957 (gethash object table)))))
958 (etypecase object
959 ((or bignum float sb-sys:system-area-pointer fixnum))
960 (sb-ext:weak-pointer
961 (call (sb-ext:weak-pointer-value object)))
962 (cons
963 (call (car object))
964 (call (cdr object))
965 (when (and ext (ignore-errors (fboundp object)))
966 (call (fdefinition object))))
967 (ratio
968 (call (numerator object))
969 (call (denominator object)))
970 (complex
971 (call (realpart object))
972 (call (realpart object)))
973 (sb-vm::instance
974 (call (sb-kernel:%instance-layout object))
975 (sb-kernel:do-instance-tagged-slot (i object)
976 (call (sb-kernel:%instance-ref object i)))
977 #+sb-thread
978 (when (typep object 'sb-thread:thread)
979 (cond ((eq object sb-thread:*current-thread*)
980 (dolist (value (sb-thread::%thread-local-references))
981 (call value))
982 (sb-vm::map-stack-references #'call))
984 ;; KLUDGE: INTERRUPT-THREAD is Not Nice (tm), but
985 ;; the alternative would be stopping the world...
986 #+sb-thread
987 (let ((sem (sb-thread:make-semaphore))
988 (refs nil))
989 (handler-case
990 (progn
991 (sb-thread:interrupt-thread
992 object
993 (lambda ()
994 (setf refs (sb-thread::%thread-local-references))
995 (sb-vm::map-stack-references (lambda (x) (push x refs)))
996 (sb-thread:signal-semaphore sem)))
997 (sb-thread:wait-on-semaphore sem))
998 (sb-thread:interrupt-thread-error ()))
999 (mapc #'call refs))))))
1000 (array
1001 (if (simple-vector-p object)
1002 (dotimes (i (length object))
1003 (call (aref object i)))
1004 (when (sb-kernel:array-header-p object)
1005 (call (sb-kernel::%array-data-vector object))
1006 (call (sb-kernel::%array-displaced-p object))
1007 (unless simple
1008 (call (sb-kernel::%array-displaced-from object))))))
1009 (sb-kernel:code-component
1010 (call (sb-kernel:%code-entry-points object))
1011 (call (sb-kernel:%code-debug-info object))
1012 (loop for i from sb-vm:code-constants-offset
1013 below (sb-kernel:get-header-data object)
1014 do (call (sb-kernel:code-header-ref object i))))
1015 (sb-kernel:fdefn
1016 (call (sb-kernel:fdefn-name object))
1017 (call (sb-kernel:fdefn-fun object)))
1018 (sb-kernel:simple-fun
1019 (unless simple
1020 (call (sb-kernel:%simple-fun-next object)))
1021 (call (sb-kernel:fun-code-header object))
1022 (call (sb-kernel:%simple-fun-name object))
1023 (call (sb-kernel:%simple-fun-arglist object))
1024 (call (sb-kernel:%simple-fun-type object))
1025 (call (sb-kernel:%simple-fun-info object)))
1026 (sb-kernel:closure
1027 (call (sb-kernel:%closure-fun object))
1028 (sb-kernel:do-closure-values (x object)
1029 (call x)))
1030 (sb-kernel:funcallable-instance
1031 (call (sb-kernel:%funcallable-instance-function object))
1032 (loop for i from 1 below (- (1+ (sb-kernel:get-closure-length object))
1033 sb-vm::funcallable-instance-info-offset)
1034 do (call (sb-kernel:%funcallable-instance-info object i))))
1035 (symbol
1036 (when ext
1037 (dolist (thread (sb-thread:list-all-threads))
1038 (call (sb-thread:symbol-value-in-thread object thread nil))))
1039 (handler-case
1040 ;; We don't have GLOBAL-BOUNDP, and there's no ERRORP arg.
1041 (call (sb-ext:symbol-global-value object))
1042 (unbound-variable ()))
1043 ;; These first two are probably unnecessary.
1044 ;; The functoid values, if present, are in SYMBOL-INFO
1045 ;; which is traversed whether or not EXT was true.
1046 ;; But should we traverse SYMBOL-INFO?
1047 ;; I don't know what is expected of this interface.
1048 (when (and ext (ignore-errors (fboundp object)))
1049 (call (fdefinition object))
1050 (call (macro-function object))
1051 (let ((class (find-class object nil)))
1052 (when class (call class))))
1053 (call (symbol-plist object)) ; perhaps SB-KERNEL:SYMBOL-INFO instead?
1054 (call (symbol-name object))
1055 (unless simple
1056 (call (symbol-package object))))
1057 (sb-kernel::random-class
1058 (case (sb-kernel:widetag-of object)
1059 (#.sb-vm::value-cell-header-widetag
1060 (call (sb-kernel::value-cell-ref object)))
1062 (warn "~&MAP-ROOT: Unknown widetag ~S: ~S~%"
1063 (sb-kernel:widetag-of object) object)))))))
1064 object)