[armedbear-cvs] r13111 - trunk/abcl/tools
Erik Huelsmann
ehuelsmann at common-lisp.net
Tue Dec 28 21:38:20 UTC 2010
Author: ehuelsmann
Date: Tue Dec 28 16:38:18 2010
New Revision: 13111
Log:
Add a tools/ directory and a code-graphing tool to visualize instruction
flow and stack depth using GraphViz.
Added:
trunk/abcl/tools/
trunk/abcl/tools/code-grapher.lisp
Added: trunk/abcl/tools/code-grapher.lisp
==============================================================================
--- (empty file)
+++ trunk/abcl/tools/code-grapher.lisp Tue Dec 28 16:38:18 2010
@@ -0,0 +1,126 @@
+
+;; Raw outlines of a graphViz tool to visualize the instruction graph of ABCL generated code.
+;; and the associated stack depths.
+
+(defvar *graph* nil)
+
+(declaim (ftype (function (t) t) branch-opcode-p))
+(declaim (inline branch-opcode-p))
+(defun branch-opcode-p (opcode)
+ (declare (optimize speed))
+ (declare (type '(integer 0 255) opcode))
+ (or (<= 153 opcode 168)
+ (= opcode 198)))
+
+(declaim (ftype (function (t t t) t) walk-code))
+(defun walk-code (code start-index depth last-instruction)
+ (declare (optimize speed))
+ (declare (type fixnum start-index depth))
+ (do* ((i start-index (1+ i))
+ (limit (length code)))
+ ((>= i limit))
+ (declare (type fixnum i limit))
+ (let* ((instruction (aref code i))
+ (instruction-depth (jvm::instruction-depth instruction))
+ (instruction-stack (jvm::instruction-stack instruction))
+ (this-instruction (format nil "i~A" i)))
+ (declare (type fixnum instruction-stack))
+ (format t "~A ~A~%" last-instruction this-instruction)
+ (push (list last-instruction this-instruction depth) *graph*)
+ (setf last-instruction this-instruction)
+ (when instruction-depth
+ (unless (= (the fixnum instruction-depth)
+ (the fixnum (+ depth instruction-stack)))
+ (internal-compiler-error
+ "Stack inconsistency detected in ~A at index ~D: found ~S, expected ~S."
+ (compiland-name *current-compiland*)
+ i instruction-depth (+ depth instruction-stack))
+ (return-from walk-code)))
+ (let ((opcode (jvm::instruction-opcode instruction)))
+ (setf depth (+ depth instruction-stack))
+ (setf (jvm::instruction-depth instruction) depth)
+ (when (branch-opcode-p opcode)
+ (let ((label (car (jvm::instruction-args instruction))))
+ (declare (type symbol label))
+ (walk-code code (symbol-value label) depth this-instruction)))
+ (when (member opcode '(167 176 191)) ; GOTO ARETURN ATHROW
+ ;; Current path ends.
+ (return-from walk-code))))))
+
+(declaim (ftype (function () t) analyze-stack))
+(defun analyze-stack ()
+ (declare (optimize speed))
+ (let* ((code *code*)
+ (code-length (length code)))
+ (declare (type vector code))
+ (dotimes (i code-length)
+ (declare (type (unsigned-byte 16) i))
+ (let* ((instruction (aref code i))
+ (opcode (jvm::instruction-opcode instruction)))
+ (when (eql opcode 202) ; LABEL
+ (let ((label (car (jvm::instruction-args instruction))))
+ (set label i)))
+ (if (jvm::instruction-stack instruction)
+ (when (jvm::opcode-stack-effect opcode)
+ (unless (eql (jvm::instruction-stack instruction)
+ (jvm::opcode-stack-effect opcode))
+ (sys::%format t "instruction-stack = ~S opcode-stack-effect = ~S~%"
+ (jvm::instruction-stack instruction)
+ (jvm::opcode-stack-effect opcode))
+ (sys::%format t "index = ~D instruction = ~A~%" i
+ (jvm::print-instruction instruction))))
+ (setf (jvm::instruction-stack instruction)
+ (jvm::opcode-stack-effect opcode)))
+ (unless (jvm::instruction-stack instruction)
+ (sys::%format t "no stack information for instruction ~D~%"
+ (jvm::instruction-opcode instruction))
+ (aver nil))))
+ (walk-code code 0 0 (gensym))
+ (dolist (handler *handlers*)
+ ;; Stack depth is always 1 when handler is called.
+ (walk-code code (symbol-value (jvm::handler-code handler)) 1 (gensym)))
+ (let ((max-stack 0))
+ (declare (type fixnum max-stack))
+ (dotimes (i code-length)
+ (declare (type (unsigned-byte 16) i))
+ (let* ((instruction (aref code i))
+ (instruction-depth (jvm::instruction-depth instruction)))
+ (when instruction-depth
+ (setf max-stack (max max-stack (the fixnum instruction-depth))))))
+;; (when *compiler-debug*
+;; (sys::%format t "compiland name = ~S~%" (compiland-name *current-compiland*))
+;; (sys::%format t "max-stack = ~D~%" max-stack)
+;; (sys::%format t "----- after stack analysis -----~%")
+;; (print-code))
+ max-stack)))
+
+
+(defvar *code*)
+(defvar *handlers*)
+(compile nil '(lambda () nil))
+(setq *handlers* nil)
+(setq *code* nil)
+(setq jvm::*saved-code* nil)
+(setq jvm::*compiler-debug* t)
+(defun f ()
+ (let ((stream (make-string-input-stream "f" 0)))
+ (read-line stream)
+ (lambda ()
+ (return-from f))))
+(ignore-errors (compile 'f))
+
+(setq *graph* nil)
+(let ((*code* (coerce (car jvm::*saved-code*) 'vector))
+ (*handlers* (car jvm::*saved-handlers*)))
+ (analyze-stack))
+(with-open-file (f #p"g.gvz" :direction :output :if-exists :supersede)
+ (format f "digraph main {~%")
+ (dolist (e *graph*)
+ (format f "~A -> ~A [label=\"~A\"];~%"
+ (first e) (second e) (third e)))
+ (let ((*code* (coerce (car jvm::*saved-code*) 'vector)))
+ (dotimes (i (length *code*))
+ (format f "i~A [label=\"~A:~A\"]~%" i i
+ (jvm::opcode-name (jvm::instruction-opcode (aref *code* i))))))
+ (format f "}~%"))
+
More information about the armedbear-cvs
mailing list