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