| 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 | |
|---|