source: trunk/abcl/tools/code-grapher.lisp

Last change on this file was 13112, checked in by Mark Evenson, 14 years ago

Set EOL to native.

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1
2;; Raw outlines of a graphViz tool to visualize the instruction graph of ABCL generated code.
3;;  and the associated stack depths.
4
5(defvar *graph* nil)
6
7(declaim (ftype (function (t) t) branch-opcode-p))
8(declaim (inline branch-opcode-p))
9(defun branch-opcode-p (opcode)
10  (declare (optimize speed))
11  (declare (type '(integer 0 255) opcode))
12  (or (<= 153 opcode 168)
13      (= opcode 198)))
14
15(declaim (ftype (function (t t t) t) walk-code))
16(defun walk-code (code start-index depth last-instruction)
17  (declare (optimize speed))
18  (declare (type fixnum start-index depth))
19  (do* ((i start-index (1+ i))
20        (limit (length code)))
21       ((>= i limit))
22    (declare (type fixnum i limit))
23    (let* ((instruction (aref code i))
24           (instruction-depth (jvm::instruction-depth instruction))
25           (instruction-stack (jvm::instruction-stack instruction))
26           (this-instruction (format nil "i~A" i)))
27      (declare (type fixnum instruction-stack))
28      (format t "~A ~A~%" last-instruction this-instruction)
29      (push (list last-instruction  this-instruction depth) *graph*)
30      (setf last-instruction this-instruction)
31      (when instruction-depth
32        (unless (= (the fixnum instruction-depth)
33                   (the fixnum (+ depth instruction-stack)))
34          (internal-compiler-error 
35           "Stack inconsistency detected in ~A at index ~D: found ~S, expected ~S." 
36           (compiland-name *current-compiland*)
37           i instruction-depth (+ depth instruction-stack))
38          (return-from walk-code)))
39      (let ((opcode (jvm::instruction-opcode instruction)))
40        (setf depth (+ depth instruction-stack))
41        (setf (jvm::instruction-depth instruction) depth)
42        (when (branch-opcode-p opcode)
43          (let ((label (car (jvm::instruction-args instruction))))
44            (declare (type symbol label))
45            (walk-code code (symbol-value label) depth this-instruction)))
46        (when (member opcode '(167 176 191)) ; GOTO ARETURN ATHROW
47          ;; Current path ends.
48          (return-from walk-code))))))
49
50(declaim (ftype (function () t) analyze-stack))
51(defun analyze-stack ()
52  (declare (optimize speed))
53  (let* ((code *code*)
54         (code-length (length code)))
55    (declare (type vector code))
56    (dotimes (i code-length)
57      (declare (type (unsigned-byte 16) i))
58      (let* ((instruction (aref code i))
59             (opcode (jvm::instruction-opcode instruction)))
60        (when (eql opcode 202) ; LABEL
61          (let ((label (car (jvm::instruction-args instruction))))
62            (set label i)))
63        (if (jvm::instruction-stack instruction)
64            (when (jvm::opcode-stack-effect opcode)
65              (unless (eql (jvm::instruction-stack instruction)
66                           (jvm::opcode-stack-effect opcode))
67                (sys::%format t "instruction-stack = ~S opcode-stack-effect = ~S~%"
68                         (jvm::instruction-stack instruction)
69                         (jvm::opcode-stack-effect opcode))
70                (sys::%format t "index = ~D instruction = ~A~%" i
71                              (jvm::print-instruction instruction))))
72            (setf (jvm::instruction-stack instruction)
73                  (jvm::opcode-stack-effect opcode)))
74        (unless (jvm::instruction-stack instruction)
75          (sys::%format t "no stack information for instruction ~D~%"
76                        (jvm::instruction-opcode instruction))
77          (aver nil))))
78    (walk-code code 0 0 (gensym))
79    (dolist (handler *handlers*)
80      ;; Stack depth is always 1 when handler is called.
81      (walk-code code (symbol-value (jvm::handler-code handler)) 1 (gensym)))
82    (let ((max-stack 0))
83      (declare (type fixnum max-stack))
84      (dotimes (i code-length)
85        (declare (type (unsigned-byte 16) i))
86        (let* ((instruction (aref code i))
87               (instruction-depth (jvm::instruction-depth instruction)))
88          (when instruction-depth
89            (setf max-stack (max max-stack (the fixnum instruction-depth))))))
90;;       (when *compiler-debug*
91;;         (sys::%format t "compiland name = ~S~%" (compiland-name *current-compiland*))
92;;         (sys::%format t "max-stack = ~D~%" max-stack)
93;;         (sys::%format t "----- after stack analysis -----~%")
94;;         (print-code))
95      max-stack)))
96
97
98(defvar *code*)
99(defvar *handlers*)
100(compile nil '(lambda () nil))
101(setq *handlers* nil)
102(setq *code* nil)
103(setq jvm::*saved-code* nil)
104(setq jvm::*compiler-debug* t)
105(defun f ()
106  (let ((stream (make-string-input-stream "f" 0)))
107    (read-line stream)
108    (lambda () 
109      (return-from f))))
110(ignore-errors  (compile 'f))
111
112(setq *graph* nil)
113(let ((*code* (coerce (car jvm::*saved-code*) 'vector))
114      (*handlers* (car jvm::*saved-handlers*)))
115  (analyze-stack))
116(with-open-file (f #p"g.gvz" :direction :output :if-exists :supersede)
117  (format f "digraph main {~%")
118  (dolist (e *graph*)
119    (format f "~A -> ~A [label=\"~A\"];~%"
120            (first e) (second e) (third e)))
121  (let ((*code* (coerce (car jvm::*saved-code*) 'vector)))
122    (dotimes (i (length *code*))
123      (format f "i~A [label=\"~A:~A\"]~%" i i
124              (jvm::opcode-name (jvm::instruction-opcode (aref *code* i))))))
125  (format f "}~%"))
126
Note: See TracBrowser for help on using the repository browser.