| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
(defvar find-gc-unsafe-list nil |
|---|
| 34 |
"The list of unsafe functions is placed here by `find-gc-unsafe'.") |
|---|
| 35 |
|
|---|
| 36 |
(defvar find-gc-source-directory) |
|---|
| 37 |
|
|---|
| 38 |
(defvar find-gc-subrs-callers nil |
|---|
| 39 |
"Alist of users of subrs, from GC testing. |
|---|
| 40 |
Each entry has the form (FUNCTION . FUNCTIONS-THAT-CALL-IT).") |
|---|
| 41 |
|
|---|
| 42 |
(defvar find-gc-subrs-called nil |
|---|
| 43 |
"Alist of subrs called, in GC testing. |
|---|
| 44 |
Each entry has the form (FUNCTION . FUNCTIONS-IT-CALLS).") |
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
(defvar find-gc-noreturn-list '(Fsignal Fthrow wrong_type_argument)) |
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 55 |
|
|---|
| 56 |
(defvar find-gc-source-files |
|---|
| 57 |
'("dispnew.c" "scroll.c" "xdisp.c" "window.c" |
|---|
| 58 |
"term.c" "cm.c" "emacs.c" "keyboard.c" "macros.c" |
|---|
| 59 |
"keymap.c" "sysdep.c" "buffer.c" "filelock.c" |
|---|
| 60 |
"insdel.c" "marker.c" "minibuf.c" "fileio.c" |
|---|
| 61 |
"dired.c" "filemode.c" "cmds.c" "casefiddle.c" |
|---|
| 62 |
"indent.c" "search.c" "regex.c" "undo.c" |
|---|
| 63 |
"alloc.c" "data.c" "doc.c" "editfns.c" |
|---|
| 64 |
"callint.c" "eval.c" "fns.c" "print.c" "lread.c" |
|---|
| 65 |
"abbrev.c" "syntax.c" "unexec.c" |
|---|
| 66 |
"bytecode.c" "process.c" "callproc.c" "doprnt.c" |
|---|
| 67 |
"x11term.c" "x11fns.c")) |
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 |
(defun find-gc-unsafe () |
|---|
| 71 |
"Return a list of unsafe functions--that is, which can call GC. |
|---|
| 72 |
Also store it in `find-gc-unsafe'." |
|---|
| 73 |
(trace-call-tree nil) |
|---|
| 74 |
(trace-use-tree) |
|---|
| 75 |
(find-unsafe-funcs 'Fgarbage_collect) |
|---|
| 76 |
(setq find-gc-unsafe-list |
|---|
| 77 |
(sort find-gc-unsafe-list |
|---|
| 78 |
(function (lambda (x y) |
|---|
| 79 |
(string-lessp (car x) (car y)))))) |
|---|
| 80 |
) |
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
|
|---|
| 88 |
(defun find-unsafe-funcs (target) |
|---|
| 89 |
(setq find-gc-unsafe-list (list (list target))) |
|---|
| 90 |
(trace-unsafe target) |
|---|
| 91 |
) |
|---|
| 92 |
|
|---|
| 93 |
(defun trace-unsafe (func) |
|---|
| 94 |
(let ((used (assq func find-gc-subrs-callers))) |
|---|
| 95 |
(or used |
|---|
| 96 |
(error "No find-gc-subrs-callers for %s" (car find-gc-unsafe-list))) |
|---|
| 97 |
(while (setq used (cdr used)) |
|---|
| 98 |
(or (assq (car used) find-gc-unsafe-list) |
|---|
| 99 |
(memq (car used) find-gc-noreturn-list) |
|---|
| 100 |
(progn |
|---|
| 101 |
(push (cons (car used) func) find-gc-unsafe-list) |
|---|
| 102 |
(trace-unsafe (car used)))))) |
|---|
| 103 |
) |
|---|
| 104 |
|
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 |
|
|---|
| 108 |
(defun trace-call-tree (&optional already-setup) |
|---|
| 109 |
(message "Setting up directories...") |
|---|
| 110 |
(or already-setup |
|---|
| 111 |
(progn |
|---|
| 112 |
|
|---|
| 113 |
(call-process "csh" nil nil nil "-c" "rm -rf /tmp/esrc") |
|---|
| 114 |
(call-process "csh" nil nil nil "-c" "mkdir /tmp/esrc") |
|---|
| 115 |
(call-process "csh" nil nil nil "-c" |
|---|
| 116 |
(format "ln -s %s/*.[ch] /tmp/esrc" |
|---|
| 117 |
find-gc-source-directory)))) |
|---|
| 118 |
(save-excursion |
|---|
| 119 |
(set-buffer (get-buffer-create "*Trace Call Tree*")) |
|---|
| 120 |
(setq find-gc-subrs-called nil) |
|---|
| 121 |
(let ((case-fold-search nil) |
|---|
| 122 |
(files find-gc-source-files) |
|---|
| 123 |
name entry) |
|---|
| 124 |
(while files |
|---|
| 125 |
(message "Compiling %s..." (car files)) |
|---|
| 126 |
(call-process "csh" nil nil nil "-c" |
|---|
| 127 |
(format "gcc -dr -c /tmp/esrc/%s -o /dev/null" |
|---|
| 128 |
(car files))) |
|---|
| 129 |
(erase-buffer) |
|---|
| 130 |
(insert-file-contents (concat "/tmp/esrc/" (car files) ".rtl")) |
|---|
| 131 |
(while (re-search-forward ";; Function \\|(call_insn " nil t) |
|---|
| 132 |
(if (= (char-after (- (point) 3)) ?o) |
|---|
| 133 |
(progn |
|---|
| 134 |
(looking-at "[a-zA-Z0-9_]+") |
|---|
| 135 |
(setq name (intern (buffer-substring (match-beginning 0) |
|---|
| 136 |
(match-end 0)))) |
|---|
| 137 |
(message "%s : %s" (car files) name) |
|---|
| 138 |
(setq entry (list name) |
|---|
| 139 |
find-gc-subrs-called (cons entry find-gc-subrs-called))) |
|---|
| 140 |
(if (looking-at ".*\n?.*\"\\([A-Za-z0-9_]+\\)\"") |
|---|
| 141 |
(progn |
|---|
| 142 |
(setq name (intern (buffer-substring (match-beginning 1) |
|---|
| 143 |
(match-end 1)))) |
|---|
| 144 |
(or (memq name (cdr entry)) |
|---|
| 145 |
(setcdr entry (cons name (cdr entry)))))))) |
|---|
| 146 |
(delete-file (concat "/tmp/esrc/" (car files) ".rtl")) |
|---|
| 147 |
(setq files (cdr files))))) |
|---|
| 148 |
) |
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 |
(defun trace-use-tree () |
|---|
| 152 |
(setq find-gc-subrs-callers (mapcar 'list (mapcar 'car find-gc-subrs-called))) |
|---|
| 153 |
(let ((ptr find-gc-subrs-called) |
|---|
| 154 |
p2 found) |
|---|
| 155 |
(while ptr |
|---|
| 156 |
(setq p2 (car ptr)) |
|---|
| 157 |
(while (setq p2 (cdr p2)) |
|---|
| 158 |
(if (setq found (assq (car p2) find-gc-subrs-callers)) |
|---|
| 159 |
(setcdr found (cons (car (car ptr)) (cdr found))))) |
|---|
| 160 |
(setq ptr (cdr ptr)))) |
|---|
| 161 |
) |
|---|
| 162 |
|
|---|
| 163 |
(provide 'find-gc) |
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
|
|---|
| 167 |
|
|---|