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