(find-gc-subrs-callers): Renamed from find-gc-subrs-used.
[bpt/emacs.git] / lisp / emacs-lisp / find-gc.el
CommitLineData
9584e63a
GM
1;;; find-gc.el --- detect functions that call the garbage collector
2
3;; Copyright (C) 1992 Free Software Foundation, Inc.
4
5;; Maintainer: FSF
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 2, or (at your option)
12;; any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
21;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22;; Boston, MA 02110-1301, USA.
9584e63a
GM
23
24;;; Commentary:
25
b63ecadb
RS
26;; Produce in find-gc-unsafe-list the set of all functions that may invoke GC.
27;; This expects the Emacs sources to live in find-gc-source-directory.
9584e63a
GM
28;; It creates a temporary working directory /tmp/esrc.
29
30;;; Code:
31
b63ecadb
RS
32(defvar find-gc-unsafe-list nil
33 "The list of unsafe functions is placed here by `find-gc-unsafe'.")
34
35(defvar find-gc-source-directory)
36
dc9c856d
RS
37(defvar find-gc-subrs-callers nil
38 "Alist of users of subrs, from GC testing.
39Each entry has the form (FUNCTION . FUNCTIONS-THAT-CALL-IT).")
40
41(defvar find-gc-subrs-called nil
42 "Alist of subrs called, in GC testing.
43Each entry has the form (FUNCTION . FUNCTIONS-IT-CALLS).")
44
b63ecadb
RS
45
46;;; Functions on this list are safe, even if they appear to be able
47;;; to call the target.
48
49(defvar find-gc-noreturn-list '(Fsignal Fthrow wrong_type_argument))
50
51;;; This was originally generated directory-files, but there were
52;;; too many files there that were not actually compiled. The
53;;; list below was created for a HP-UX 7.0 system.
54
55(defvar find-gc-source-files
56 '("dispnew.c" "scroll.c" "xdisp.c" "window.c"
57 "term.c" "cm.c" "emacs.c" "keyboard.c" "macros.c"
58 "keymap.c" "sysdep.c" "buffer.c" "filelock.c"
59 "insdel.c" "marker.c" "minibuf.c" "fileio.c"
60 "dired.c" "filemode.c" "cmds.c" "casefiddle.c"
61 "indent.c" "search.c" "regex.c" "undo.c"
62 "alloc.c" "data.c" "doc.c" "editfns.c"
63 "callint.c" "eval.c" "fns.c" "print.c" "lread.c"
64 "abbrev.c" "syntax.c" "unexec.c"
65 "bytecode.c" "process.c" "callproc.c" "doprnt.c"
66 "x11term.c" "x11fns.c"))
67
68
9584e63a 69(defun find-gc-unsafe ()
b63ecadb
RS
70 "Return a list of unsafe functions--that is, which can call GC.
71Also store it in `find-gc-unsafe'."
9584e63a
GM
72 (trace-call-tree nil)
73 (trace-use-tree)
74 (find-unsafe-funcs 'Fgarbage_collect)
b63ecadb
RS
75 (setq find-gc-unsafe-list
76 (sort find-gc-unsafe-list
77 (function (lambda (x y)
78 (string-lessp (car x) (car y))))))
9584e63a
GM
79)
80
9584e63a
GM
81;;; This does a depth-first search to find all functions that can
82;;; ultimately call the function "target". The result is an a-list
b63ecadb 83;;; in find-gc-unsafe-list; the cars are the unsafe functions, and the cdrs
9584e63a
GM
84;;; are (one of) the unsafe functions that these functions directly
85;;; call.
86
87(defun find-unsafe-funcs (target)
b63ecadb 88 (setq find-gc-unsafe-list (list (list target)))
9584e63a
GM
89 (trace-unsafe target)
90)
91
92(defun trace-unsafe (func)
dc9c856d 93 (let ((used (assq func find-gc-subrs-callers)))
9584e63a 94 (or used
dc9c856d 95 (error "No find-gc-subrs-callers for %s" (car find-gc-unsafe-list)))
9584e63a 96 (while (setq used (cdr used))
b63ecadb
RS
97 (or (assq (car used) find-gc-unsafe-list)
98 (memq (car used) find-gc-noreturn-list)
9584e63a 99 (progn
b63ecadb 100 (push (cons (car used) func) find-gc-unsafe-list)
9584e63a
GM
101 (trace-unsafe (car used))))))
102)
103
104
9584e63a 105
9584e63a
GM
106
107(defun trace-call-tree (&optional already-setup)
108 (message "Setting up directories...")
109 (or already-setup
110 (progn
111 ;; Gee, wouldn't a built-in "system" function be handy here.
112 (call-process "csh" nil nil nil "-c" "rm -rf /tmp/esrc")
113 (call-process "csh" nil nil nil "-c" "mkdir /tmp/esrc")
114 (call-process "csh" nil nil nil "-c"
115 (format "ln -s %s/*.[ch] /tmp/esrc"
b63ecadb 116 find-gc-source-directory))))
9584e63a
GM
117 (save-excursion
118 (set-buffer (get-buffer-create "*Trace Call Tree*"))
dc9c856d 119 (setq find-gc-subrs-called nil)
9584e63a 120 (let ((case-fold-search nil)
b63ecadb 121 (files find-gc-source-files)
9584e63a
GM
122 name entry)
123 (while files
124 (message "Compiling %s..." (car files))
125 (call-process "csh" nil nil nil "-c"
126 (format "gcc -dr -c /tmp/esrc/%s -o /dev/null"
127 (car files)))
128 (erase-buffer)
129 (insert-file-contents (concat "/tmp/esrc/" (car files) ".rtl"))
130 (while (re-search-forward ";; Function \\|(call_insn " nil t)
131 (if (= (char-after (- (point) 3)) ?o)
132 (progn
133 (looking-at "[a-zA-Z0-9_]+")
134 (setq name (intern (buffer-substring (match-beginning 0)
135 (match-end 0))))
136 (message "%s : %s" (car files) name)
137 (setq entry (list name)
dc9c856d 138 find-gc-subrs-called (cons entry find-gc-subrs-called)))
9584e63a
GM
139 (if (looking-at ".*\n?.*\"\\([A-Za-z0-9_]+\\)\"")
140 (progn
141 (setq name (intern (buffer-substring (match-beginning 1)
142 (match-end 1))))
143 (or (memq name (cdr entry))
144 (setcdr entry (cons name (cdr entry))))))))
145 (delete-file (concat "/tmp/esrc/" (car files) ".rtl"))
146 (setq files (cdr files)))))
147)
148
149
9584e63a 150(defun trace-use-tree ()
dc9c856d
RS
151 (setq find-gc-subrs-callers (mapcar 'list (mapcar 'car find-gc-subrs-called)))
152 (let ((ptr find-gc-subrs-called)
9584e63a
GM
153 p2 found)
154 (while ptr
155 (setq p2 (car ptr))
156 (while (setq p2 (cdr p2))
dc9c856d 157 (if (setq found (assq (car p2) find-gc-subrs-callers))
9584e63a
GM
158 (setcdr found (cons (car (car ptr)) (cdr found)))))
159 (setq ptr (cdr ptr))))
160)
161
162(provide 'find-gc)
163
ab5796a9 164;;; arch-tag: 4a26a538-a008-40d9-a1ef-23bb6dbecef4
9584e63a 165;;; find-gc.el ends here