source: trunk/abcl/src/org/armedbear/lisp/jvm-instructions.lisp @ 13710

Last change on this file since 13710 was 13710, checked in by astalla, 12 years ago

First stab at restoring runtime-class.
Supported: extending a Java class, implementing interfaces, defining methods
of up to 7 non-primitive arguments returning void or a non-primitive object.
Unsupported: everything else, including fields, constructors, annotations,
primitive arguments and return values, and the LispObject[] call convention
for functions with more than 8 arguments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 36.2 KB
Line 
1;;; jvm-instructions.lisp
2;;;
3;;; Copyright (C) 2003-2006 Peter Graves
4;;; Copyright (C) 2010 Erik Huelsmann
5;;; $Id: jvm-instructions.lisp 13710 2011-12-27 19:50:08Z astalla $
6;;;
7;;; This program is free software; you can redistribute it and/or
8;;; modify it under the terms of the GNU General Public License
9;;; as published by the Free Software Foundation; either version 2
10;;; of the License, or (at your option) any later version.
11;;;
12;;; This program is distributed in the hope that it will be useful,
13;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
18;;; along with this program; if not, write to the Free Software
19;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20;;;
21;;; As a special exception, the copyright holders of this library give you
22;;; permission to link this library with independent modules to produce an
23;;; executable, regardless of the license terms of these independent
24;;; modules, and to copy and distribute the resulting executable under
25;;; terms of your choice, provided that you also meet, for each linked
26;;; independent module, the terms and conditions of the license of that
27;;; module.  An independent module is a module which is not derived from
28;;; or based on this library.  If you modify this library, you may extend
29;;; this exception to your version of the library, but you are not
30;;; obligated to do so.  If you do not wish to do so, delete this
31;;; exception statement from your version.
32
33(in-package #:jvm)
34
35
36;;    OPCODES
37
38(defconst *opcode-table* (make-array 256))
39
40(defconst *opcodes* (make-hash-table :test 'equalp))
41
42(defstruct jvm-opcode name number size stack-effect register-used)
43
44(defun %define-opcode (name number size stack-effect register)
45  (declare (type fixnum number size))
46  (let* ((name (string name))
47         (opcode (make-jvm-opcode :name name
48                                  :number number
49                                  :size size
50                                  :stack-effect stack-effect
51                                  :register-used register)))
52     (setf (svref *opcode-table* number) opcode)
53     (setf (gethash name *opcodes*) opcode)
54     (setf (gethash number *opcodes*) opcode)))
55
56(defmacro define-opcode (name number size stack-effect register)
57  `(%define-opcode ',name ,number ,size ,stack-effect ,register))
58
59;; name number size stack-effect register-used
60(define-opcode nop 0 1 0 nil)
61(define-opcode aconst_null 1 1 1 nil)
62(define-opcode iconst_m1 2 1 1 nil)
63(define-opcode iconst_0 3 1 1 nil)
64(define-opcode iconst_1 4 1 1 nil)
65(define-opcode iconst_2 5 1 1 nil)
66(define-opcode iconst_3 6 1 1 nil)
67(define-opcode iconst_4 7 1 1 nil)
68(define-opcode iconst_5 8 1 1 nil)
69(define-opcode lconst_0 9 1 2 nil)
70(define-opcode lconst_1 10 1 2 nil)
71(define-opcode fconst_0 11 1 1 nil)
72(define-opcode fconst_1 12 1 1 nil)
73(define-opcode fconst_2 13 1 1 nil)
74(define-opcode dconst_0 14 1 2 nil)
75(define-opcode dconst_1 15 1 2 nil)
76(define-opcode bipush 16 2 1 nil)
77(define-opcode sipush 17 3 1 nil)
78(define-opcode ldc 18 2 1 nil)
79(define-opcode ldc_w 19 3 1 nil)
80(define-opcode ldc2_w 20 3 2 nil)
81(define-opcode iload 21 2 1 t)
82(define-opcode lload 22 2 2 t)
83(define-opcode fload 23 2 nil t)
84(define-opcode dload 24 2 nil t)
85(define-opcode aload 25 2 1 t)
86(define-opcode iload_0 26 1 1 0)
87(define-opcode iload_1 27 1 1 1)
88(define-opcode iload_2 28 1 1 2)
89(define-opcode iload_3 29 1 1 3)
90(define-opcode lload_0 30 1 2 0)
91(define-opcode lload_1 31 1 2 1)
92(define-opcode lload_2 32 1 2 2)
93(define-opcode lload_3 33 1 2 3)
94(define-opcode fload_0 34 1 nil 0)
95(define-opcode fload_1 35 1 nil 1)
96(define-opcode fload_2 36 1 nil 2)
97(define-opcode fload_3 37 1 nil 3)
98(define-opcode dload_0 38 1 nil 0)
99(define-opcode dload_1 39 1 nil 1)
100(define-opcode dload_2 40 1 nil 2)
101(define-opcode dload_3 41 1 nil 3)
102(define-opcode aload_0 42 1 1 0)
103(define-opcode aload_1 43 1 1 1)
104(define-opcode aload_2 44 1 1 2)
105(define-opcode aload_3 45 1 1 3)
106(define-opcode iaload 46 1 -1 nil)
107(define-opcode laload 47 1 0 nil)
108(define-opcode faload 48 1 -1 nil)
109(define-opcode daload 49 1 0 nil)
110(define-opcode aaload 50 1 -1 nil)
111(define-opcode baload 51 1 nil nil)
112(define-opcode caload 52 1 nil nil)
113(define-opcode saload 53 1 nil nil)
114(define-opcode istore 54 2 -1 t)
115(define-opcode lstore 55 2 -2 t)
116(define-opcode fstore 56 2 nil t)
117(define-opcode dstore 57 2 nil t)
118(define-opcode astore 58 2 -1 t)
119(define-opcode istore_0 59 1 -1 0)
120(define-opcode istore_1 60 1 -1 1)
121(define-opcode istore_2 61 1 -1 2)
122(define-opcode istore_3 62 1 -1 3)
123(define-opcode lstore_0 63 1 -2 0)
124(define-opcode lstore_1 64 1 -2 1)
125(define-opcode lstore_2 65 1 -2 2)
126(define-opcode lstore_3 66 1 -2 3)
127(define-opcode fstore_0 67 1 nil 0)
128(define-opcode fstore_1 68 1 nil 1)
129(define-opcode fstore_2 69 1 nil 2)
130(define-opcode fstore_3 70 1 nil 3)
131(define-opcode dstore_0 71 1 nil 0)
132(define-opcode dstore_1 72 1 nil 1)
133(define-opcode dstore_2 73 1 nil 2)
134(define-opcode dstore_3 74 1 nil 3)
135(define-opcode astore_0 75 1 -1 0)
136(define-opcode astore_1 76 1 -1 1)
137(define-opcode astore_2 77 1 -1 2)
138(define-opcode astore_3 78 1 -1 3)
139(define-opcode iastore 79 1 -3 nil)
140(define-opcode lastore 80 1 -4 nil)
141(define-opcode fastore 81 1 -3 nil)
142(define-opcode dastore 82 1 -4 nil)
143(define-opcode aastore 83 1 -3 nil)
144(define-opcode bastore 84 1 nil nil)
145(define-opcode castore 85 1 nil nil)
146(define-opcode sastore 86 1 nil nil)
147(define-opcode pop 87 1 -1 nil)
148(define-opcode pop2 88 1 -2 nil)
149(define-opcode dup 89 1 1 nil)
150(define-opcode dup_x1 90 1 1 nil)
151(define-opcode dup_x2 91 1 1 nil)
152(define-opcode dup2 92 1 2 nil)
153(define-opcode dup2_x1 93 1 2 nil)
154(define-opcode dup2_x2 94 1 2 nil)
155(define-opcode swap 95 1 0 nil)
156(define-opcode iadd 96 1 -1 nil)
157(define-opcode ladd 97 1 -2 nil)
158(define-opcode fadd 98 1 -1 nil)
159(define-opcode dadd 99 1 -2 nil)
160(define-opcode isub 100 1 -1 nil)
161(define-opcode lsub 101 1 -2 nil)
162(define-opcode fsub 102 1 -1 nil)
163(define-opcode dsub 103 1 -2 nil)
164(define-opcode imul 104 1 -1 nil)
165(define-opcode lmul 105 1 -2 nil)
166(define-opcode fmul 106 1 -1 nil)
167(define-opcode dmul 107 1 -2 nil)
168(define-opcode idiv 108 1 nil nil)
169(define-opcode ldiv 109 1 nil nil)
170(define-opcode fdiv 110 1 nil nil)
171(define-opcode ddiv 111 1 nil nil)
172(define-opcode irem 112 1 nil nil)
173(define-opcode lrem 113 1 nil nil)
174(define-opcode frem 114 1 nil nil)
175(define-opcode drem 115 1 nil nil)
176(define-opcode ineg 116 1 0 nil)
177(define-opcode lneg 117 1 0 nil)
178(define-opcode fneg 118 1 0 nil)
179(define-opcode dneg 119 1 0 nil)
180(define-opcode ishl 120 1 -1 nil)
181(define-opcode lshl 121 1 -1 nil)
182(define-opcode ishr 122 1 -1 nil)
183(define-opcode lshr 123 1 -1 nil)
184(define-opcode iushr 124 1 nil nil)
185(define-opcode lushr 125 1 nil nil)
186(define-opcode iand 126 1 -1 nil)
187(define-opcode land 127 1 -2 nil)
188(define-opcode ior 128 1 -1 nil)
189(define-opcode lor 129 1 -2 nil)
190(define-opcode ixor 130 1 -1 nil)
191(define-opcode lxor 131 1 -2 nil)
192(define-opcode iinc 132 3 0 t)
193(define-opcode i2l 133 1 1 nil)
194(define-opcode i2f 134 1 0 nil)
195(define-opcode i2d 135 1 1 nil)
196(define-opcode l2i 136 1 -1 nil)
197(define-opcode l2f 137 1 -1 nil)
198(define-opcode l2d 138 1 0 nil)
199(define-opcode f2i 139 1 nil nil)
200(define-opcode f2l 140 1 nil nil)
201(define-opcode f2d 141 1 1 nil)
202(define-opcode d2i 142 1 nil nil)
203(define-opcode d2l 143 1 nil nil)
204(define-opcode d2f 144 1 -1 nil)
205(define-opcode i2b 145 1 nil nil)
206(define-opcode i2c 146 1 nil nil)
207(define-opcode i2s 147 1 nil nil)
208(define-opcode lcmp 148 1 -3 nil)
209(define-opcode fcmpl 149 1 -1 nil)
210(define-opcode fcmpg 150 1 -1 nil)
211(define-opcode dcmpl 151 1 -3 nil)
212(define-opcode dcmpg 152 1 -3 nil)
213(define-opcode ifeq 153 3 -1 nil)
214(define-opcode ifne 154 3 -1 nil)
215(define-opcode iflt 155 3 -1 nil)
216(define-opcode ifge 156 3 -1 nil)
217(define-opcode ifgt 157 3 -1 nil)
218(define-opcode ifle 158 3 -1 nil)
219(define-opcode if_icmpeq 159 3 -2 nil)
220(define-opcode if_icmpne 160 3 -2 nil)
221(define-opcode if_icmplt 161 3 -2 nil)
222(define-opcode if_icmpge 162 3 -2 nil)
223(define-opcode if_icmpgt 163 3 -2 nil)
224(define-opcode if_icmple 164 3 -2 nil)
225(define-opcode if_acmpeq 165 3 -2 nil)
226(define-opcode if_acmpne 166 3 -2 nil)
227(define-opcode goto 167 3 0 nil)
228;;(define-opcode jsr 168 3 1) Don't use these 2 opcodes: deprecated
229;;(define-opcode ret 169 2 0) their use results in JVM verifier errors
230(define-opcode tableswitch 170 0 nil nil)
231(define-opcode lookupswitch 171 0 nil nil)
232(define-opcode ireturn 172 1 nil nil)
233(define-opcode lreturn 173 1 nil nil)
234(define-opcode freturn 174 1 nil nil)
235(define-opcode dreturn 175 1 nil nil)
236(define-opcode ireturn 172 1 -1 nil)
237(define-opcode areturn 176 1 -1 nil)
238(define-opcode return 177 1 0 nil)
239(define-opcode getstatic 178 3 1 nil)
240(define-opcode putstatic 179 3 -1 nil)
241(define-opcode getfield 180 3 0 nil)
242(define-opcode putfield 181 3 -2 nil)
243(define-opcode invokevirtual 182 3 nil nil)
244(define-opcode invokespecial 183 3 nil nil)
245(define-opcode invokestatic 184 3 nil nil)
246(define-opcode invokeinterface 185 5 nil nil)
247(define-opcode unused 186 0 nil nil)
248(define-opcode new 187 3 1 nil)
249(define-opcode newarray 188 2 nil nil)
250(define-opcode anewarray 189 3 0 nil)
251(define-opcode arraylength 190 1 0 nil)
252(define-opcode athrow 191 1 0 nil)
253(define-opcode checkcast 192 3 0 nil)
254(define-opcode instanceof 193 3 0 nil)
255(define-opcode monitorenter 194 1 -1 nil)
256(define-opcode monitorexit 195 1 -1 nil)
257(define-opcode wide 196 0 nil nil)
258(define-opcode multianewarray 197 4 nil nil)
259(define-opcode ifnull 198 3 -1 nil)
260(define-opcode ifnonnull 199 3 nil nil)
261(define-opcode goto_w 200 5 nil nil)
262;; (define-opcode jsr_w 201 5 nil) Don't use: deprecated
263(define-opcode label 202 0 0 nil)  ;; virtual: does not exist in the JVM
264;; (define-opcode push-value 203 nil 1)
265;; (define-opcode store-value 204 nil -1)
266(define-opcode clear-values 205 0 0 t)  ;; virtual: does not exist in the JVM
267;;(define-opcode var-ref 206 0 0)
268
269(defparameter *last-opcode* 206)
270
271(declaim (ftype (function (t) t) opcode-name))
272(defun opcode-name (opcode-number)
273  (let ((opcode (gethash opcode-number *opcodes*)))
274    (and opcode (jvm-opcode-name opcode))))
275
276(declaim (ftype (function (t) (integer 0 255)) opcode-number))
277(defun opcode-number (opcode-name)
278  (declare (optimize speed))
279  (let ((opcode (gethash (string opcode-name) *opcodes*)))
280    (if opcode
281        (jvm-opcode-number opcode)
282        (error "Unknown opcode ~S." opcode-name))))
283
284(declaim (ftype (function (t) fixnum) opcode-size))
285(defun opcode-size (opcode-number)
286  (declare (optimize speed (safety 0)))
287  (declare (type (integer 0 255) opcode-number))
288  (jvm-opcode-size (svref *opcode-table* opcode-number)))
289
290(declaim (ftype (function (t) t) opcode-stack-effect))
291(defun opcode-stack-effect (opcode-number)
292  (declare (optimize speed))
293  (jvm-opcode-stack-effect (svref *opcode-table* opcode-number)))
294
295
296
297
298;;   INSTRUCTION
299
300(defstruct (instruction (:constructor %make-instruction (opcode args)))
301  (opcode 0 :type (integer 0 255))
302  args
303  stack
304  depth
305  wide)
306
307(defun make-instruction (opcode args)
308  (let ((inst (apply #'%make-instruction
309                     (list opcode
310                           (remove :wide-prefix args)))))
311    (when (memq :wide-prefix args)
312      (setf (inst-wide inst) t))
313    inst))
314
315(defun print-instruction (instruction)
316  (sys::%format nil "~A ~A stack = ~S depth = ~S"
317          (opcode-name (instruction-opcode instruction))
318          (instruction-args instruction)
319          (instruction-stack instruction)
320          (instruction-depth instruction)))
321
322(declaim (ftype (function (t) t) instruction-label))
323(defun instruction-label (instruction)
324  (and instruction
325       (= (instruction-opcode (the instruction instruction)) 202)
326       (car (instruction-args instruction))))
327
328
329
330(defknown inst * t)
331(defun inst (instr &optional args)
332  (declare (optimize speed))
333  (let ((opcode (if (fixnump instr)
334                    instr
335                    (opcode-number instr))))
336    (unless (listp args)
337      (setf args (list args)))
338    (make-instruction opcode args)))
339
340
341;; Having %emit and %%emit output their code to *code*
342;; is currently an implementation detail exposed to all users.
343;; We need to have APIs to address this, but for now pass2 is
344;; our only user and we'll hard-code the use of *code*.
345(defvar *code* nil)
346
347(defknown %%emit * t)
348(defun %%emit (instr &rest args)
349  (declare (optimize speed))
350  (let ((instruction (make-instruction instr args)))
351    (push instruction *code*)
352    instruction))
353
354(defknown %emit * t)
355(defun %emit (instr &rest args)
356  (declare (optimize speed))
357  (let ((instruction (inst instr args)))
358    (push instruction *code*)
359    instruction))
360
361(defmacro emit (instr &rest args)
362  (when (and (consp instr)
363             (eq (car instr) 'QUOTE)
364             (symbolp (cadr instr)))
365    (setf instr (opcode-number (cadr instr))))
366  (if (fixnump instr)
367      `(%%emit ,instr ,@args)
368      `(%emit ,instr ,@args)))
369
370
371;;  Helper routines
372
373(defknown label (symbol) t)
374(defun label (symbol)
375  (declare (type symbol symbol))
376  (declare (optimize speed))
377  (emit 'label symbol)
378  (setf (symbol-value symbol) nil))
379
380(defknown aload (fixnum) t)
381(defun aload (index)
382  (case index
383    (0 (emit 'aload_0))
384    (1 (emit 'aload_1))
385    (2 (emit 'aload_2))
386    (3 (emit 'aload_3))
387    (t (emit 'aload index))))
388
389(defknown astore (fixnum) t)
390(defun astore (index)
391  (case index
392    (0 (emit 'astore_0))
393    (1 (emit 'astore_1))
394    (2 (emit 'astore_2))
395    (3 (emit 'astore_3))
396    (t (emit 'astore index))))
397
398(declaim (ftype (function (t) t) branch-p)
399         (inline branch-p))
400(defun branch-p (opcode)
401;;  (declare (optimize speed))
402;;  (declare (type '(integer 0 255) opcode))
403  (or (<= 153 opcode 167)
404      (<= 198 opcode 200))) ;; ifnull / ifnonnull / goto_w
405
406(declaim (ftype (function (t) t) unconditional-control-transfer-p)
407         (inline unconditional-control-transfer-p))
408(defun unconditional-control-transfer-p (opcode)
409  (or (= 167 opcode) ;; goto
410      (= 200 opcode) ;; goto_w
411      (<= 172 opcode 177) ;; ?return
412      (= 191 opcode) ;; athrow
413      ))
414
415(declaim (ftype (function (t) boolean) label-p)
416         (inline label-p))
417(defun label-p (instruction)
418  (and instruction
419       (= (the fixnum (instruction-opcode (the instruction instruction))) 202)))
420
421(defun print-code (code)
422  (dotimes (i (length code))
423    (let ((instruction (elt code i)))
424      (sys::%format t "~D ~A ~S ~S ~S~%"
425                    i
426                    (opcode-name (instruction-opcode instruction))
427                    (instruction-args instruction)
428                    (instruction-stack instruction)
429                    (instruction-depth instruction)))))
430
431(defun print-code2 (code)
432  (dotimes (i (length code))
433    (let ((instruction (elt code i)))
434      (case (instruction-opcode instruction)
435        (202 ; LABEL
436         (format t "~A:~%" (car (instruction-args instruction))))
437        (t
438         (format t "~8D:   ~A ~S~%"
439                 i
440                 (opcode-name (instruction-opcode instruction))
441                 (instruction-args instruction)))))))
442
443(defun expand-virtual-instructions (code)
444  (let* ((len (length code))
445         (vector (make-array (ash len 1) :fill-pointer 0 :adjustable t)))
446    (dotimes (index len vector)
447      (declare (type (unsigned-byte 16) index))
448      (let ((instruction (svref code index)))
449        (case (instruction-opcode instruction)
450          (205 ; CLEAR-VALUES
451           (dolist (instruction
452                     (list
453                      (inst 'aload (car (instruction-args instruction)))
454                      (inst 'aconst_null)
455                      (inst 'putfield (u2 (pool-field +lisp-thread+ "_values"
456                                                      +lisp-object-array+)))))
457             (vector-push-extend instruction vector)))
458          (t
459           (vector-push-extend instruction vector)))))))
460
461
462;;   RESOLVERS
463
464(defun unsupported-opcode (instruction)
465  (error "Unsupported opcode ~D." (instruction-opcode instruction)))
466
467(declaim (type hash-table +resolvers+))
468(defconst +resolvers+ (make-hash-table))
469
470(defun initialize-resolvers ()
471  (let ((ht +resolvers+))
472    (dotimes (n (1+ *last-opcode*))
473      (setf (gethash n ht) #'unsupported-opcode))
474    ;; The following opcodes resolve to themselves.
475    (dolist (n '(0 ; nop
476                 1 ; aconst_null
477                 2 ; iconst_m1
478                 3 ; iconst_0
479                 4 ; iconst_1
480                 5 ; iconst_2
481                 6 ; iconst_3
482                 7 ; iconst_4
483                 8 ; iconst_5
484                 9 ; lconst_0
485                 10 ; lconst_1
486                 11 ; fconst_0
487                 12 ; fconst_1
488                 13 ; fconst_2
489                 14 ; dconst_0
490                 15 ; dconst_1
491                 42 ; aload_0
492                 43 ; aload_1
493                 44 ; aload_2
494                 45 ; aload_3
495                 46 ; iaload
496                 47 ; laload
497                 48 ; faload
498                 49 ; daload
499                 50 ; aaload
500                 75 ; astore_0
501                 76 ; astore_1
502                 77 ; astore_2
503                 78 ; astore_3
504                 79 ; iastore
505                 80 ; lastore
506                 81 ; fastore
507                 82 ; dastore
508                 83 ; aastore
509                 87 ; pop
510                 88 ; pop2
511                 89 ; dup
512                 90 ; dup_x1
513                 91 ; dup_x2
514                 92 ; dup2
515                 93 ; dup2_x1
516                 94 ; dup2_x2
517                 95 ; swap
518                 96 ; iadd
519                 97 ; ladd
520                 98 ; fadd
521                 99 ; dadd
522                 100 ; isub
523                 101 ; lsub
524                 102 ; fsub
525                 103 ; dsub
526                 104 ; imul
527                 105 ; lmul
528                 106 ; fmul
529                 107 ; dmul
530                 116 ; ineg
531                 117 ; lneg
532                 118 ; fneg
533                 119 ; dneg
534                 120 ; ishl
535                 121 ; lshl
536                 122 ; ishr
537                 123 ; lshr
538                 126 ; iand
539                 127 ; land
540                 128 ; ior
541                 129 ; lor
542                 130 ; ixor
543                 131 ; lxor
544                 133 ; i2l
545                 134 ; i2f
546                 135 ; i2d
547                 136 ; l2i
548                 137 ; l2f
549                 138 ; l2d
550                 141 ; f2d
551                 144 ; d2f
552                 148 ; lcmp
553                 149 ; fcmpd
554                 150 ; fcmpg
555                 151 ; dcmpd
556                 152 ; dcmpg
557                 153 ; ifeq
558                 154 ; ifne
559                 155 ; ifge
560                 156 ; ifgt
561                 157 ; ifgt
562                 158 ; ifle
563                 159 ; if_icmpeq
564                 160 ; if_icmpne
565                 161 ; if_icmplt
566                 162 ; if_icmpge
567                 163 ; if_icmpgt
568                 164 ; if_icmple
569                 165 ; if_acmpeq
570                 166 ; if_acmpne
571                 167 ; goto
572                 172 ; ireturn
573                 176 ; areturn
574                 177 ; return
575                 178 ; getstatic
576                 179 ; putstatic
577                 180 ; getfield
578                 181 ; putfield
579                 182 ; invokevirtual
580                 183 ; invockespecial
581                 184 ; invokestatic
582                 187 ; new
583                 189 ; anewarray
584                 190 ; arraylength
585                 191 ; athrow
586                 192 ; checkcast
587                 193 ; instanceof
588                 194 ; monitorenter
589                 195 ; monitorexit
590                 198 ; ifnull
591                 202 ; label
592                 ))
593      (setf (gethash n ht) nil))))
594
595(initialize-resolvers)
596
597(defmacro define-resolver (opcodes args &body body)
598  (let ((name (gensym)))
599    `(progn
600       (defun ,name ,args ,@body)
601       (eval-when (:load-toplevel :execute)
602         ,(if (listp opcodes)
603              `(dolist (op ',opcodes)
604                 (setf (gethash op +resolvers+)
605                       (symbol-function ',name)))
606              `(setf (gethash ,opcodes +resolvers+)
607                     (symbol-function ',name)))))))
608
609(defun load/store-resolver (instruction inst-index inst-index2 error-text)
610 (let* ((args (instruction-args instruction))
611        (index (car args)))
612   (declare (type (unsigned-byte 16) index))
613   (cond ((<= 0 index 3)
614          (inst (+ index inst-index)))
615         ((<= 0 index 255)
616          (inst inst-index2 index))
617         (t
618          (error error-text)))))
619
620;; aload
621(define-resolver 25 (instruction)
622  (load/store-resolver instruction 42 25 "ALOAD unsupported case"))
623
624;; astore
625(define-resolver 58 (instruction)
626  (load/store-resolver instruction 75 58 "ASTORE unsupported case"))
627
628;; iload
629(define-resolver 21 (instruction)
630  (load/store-resolver instruction 26 21 "ILOAD unsupported case"))
631
632;; istore
633(define-resolver 54 (instruction)
634  (load/store-resolver instruction 59 54 "ISTORE unsupported case"))
635
636;; lload
637(define-resolver 22 (instruction)
638  (load/store-resolver instruction 30 22 "LLOAD unsupported case"))
639
640;; lstore
641(define-resolver 55 (instruction)
642  (load/store-resolver instruction 63 55 "LSTORE unsupported case"))
643
644;; bipush, sipush
645(define-resolver (16 17) (instruction)
646  (let* ((args (instruction-args instruction))
647         (n (first args)))
648    (declare (type fixnum n))
649    (cond ((<= 0 n 5)
650           (inst (+ n 3)))
651          ((<= -128 n 127)
652           (inst 16 (logand n #xff))) ; BIPUSH
653          (t ; SIPUSH
654           (inst 17 (s2 n))))))
655
656;; ldc
657(define-resolver 18 (instruction)
658  (let* ((args (instruction-args instruction)))
659    (unless (= (length args) 1)
660      (error "Wrong number of args for LDC."))
661    (if (> (car args) 255)
662        (inst 19 (u2 (car args))) ; LDC_W
663        (inst 18 args))))
664
665;; ldc_w
666(define-resolver 19 (instruction)
667  (let* ((args (instruction-args instruction)))
668    (unless (= (length args) 1)
669      (error "Wrong number of args for LDC_W."))
670    (inst 19 (u2 (car args)))))
671
672;; ldc2_w
673(define-resolver 20 (instruction)
674  (let* ((args (instruction-args instruction)))
675    (unless (= (length args) 1)
676      (error "Wrong number of args for LDC2_W."))
677    (inst 20 (u2 (car args)))))
678
679;; iinc
680(define-resolver 132 (instruction)
681  (let* ((args (instruction-args instruction))
682         (register (first args))
683         (n (second args)))
684    (when (not (<= -128 n 127))
685      (error "IINC argument ~A out of bounds." n))
686    (inst 132 (list register (s1 n)))))
687
688(defknown resolve-instruction (t) t)
689(defun resolve-instruction (instruction)
690  (declare (optimize speed))
691  (let ((resolver (gethash1 (instruction-opcode instruction) +resolvers+)))
692    (if resolver
693        (funcall resolver instruction)
694        instruction)))
695
696(defun resolve-instructions (code)
697  (let* ((len (length code))
698         (vector (make-array len :fill-pointer 0 :adjustable t)))
699    (dotimes (index len vector)
700      (declare (type (unsigned-byte 16) index))
701      (let ((instruction (aref code index)))
702        (vector-push-extend (resolve-instruction instruction) vector)))))
703
704
705
706;; BYTE CODE ANALYSIS AND OPTIMIZATION
707
708(declaim (ftype (function (t t t) t) analyze-stack-path))
709(defun analyze-stack-path (code start-index depth)
710  (declare (optimize speed))
711  (declare (type fixnum start-index depth))
712  (do* ((i start-index (1+ i))
713        (limit (length code)))
714       ((>= i limit))
715    (declare (type fixnum i limit))
716    (let* ((instruction (aref code i))
717           (instruction-depth (instruction-depth instruction))
718           (instruction-stack (instruction-stack instruction)))
719      (declare (type fixnum instruction-stack))
720      (when instruction-depth
721        (unless (= (the fixnum instruction-depth)
722                   (the fixnum (+ depth instruction-stack)))
723          (internal-compiler-error "Stack inconsistency detected ~
724                                    in ~A at index ~D: ~
725                                    found ~S, expected ~S."
726                                   (if *current-compiland*
727                                       (compiland-name *current-compiland*)
728                                       "<unknown>")
729                                   i instruction-depth
730                                   (+ depth instruction-stack)))
731        (return-from analyze-stack-path))
732      (let ((opcode (instruction-opcode instruction)))
733        (setf depth (+ depth instruction-stack))
734        (setf (instruction-depth instruction) depth)
735        (unless (<= 0 depth)
736          (internal-compiler-error "Stack inconsistency detected ~
737                                    in ~A at index ~D: ~
738                                    negative depth ~S."
739                                   (if *current-compiland*
740                                       (compiland-name *current-compiland*)
741                                       "<unknown>")
742                                   i depth))
743        (when (branch-p opcode)
744          (let ((label (car (instruction-args instruction))))
745            (declare (type symbol label))
746            (analyze-stack-path code (symbol-value label) depth)))
747        (when (unconditional-control-transfer-p opcode)
748          ;; Current path ends.
749          (return-from analyze-stack-path))))))
750
751(declaim (ftype (function (t) t) analyze-stack))
752(defun analyze-stack (code exception-entry-points)
753  (declare (optimize speed))
754  (let* ((code-length (length code)))
755    (declare (type vector code))
756    (dotimes (i code-length)
757      (let* ((instruction (aref code i))
758             (opcode (instruction-opcode instruction)))
759        (when (eql opcode 202) ; LABEL
760          (let ((label (car (instruction-args instruction))))
761            (set label i)))
762        (if (instruction-stack instruction)
763            (when (opcode-stack-effect opcode)
764              (unless (eql (instruction-stack instruction)
765                           (opcode-stack-effect opcode))
766                (sys::%format t "instruction-stack = ~S ~
767                                 opcode-stack-effect = ~S~%"
768                              (instruction-stack instruction)
769                              (opcode-stack-effect opcode))
770                (sys::%format t "index = ~D instruction = ~A~%" i
771                              (print-instruction instruction))))
772            (setf (instruction-stack instruction)
773                  (opcode-stack-effect opcode)))
774        (unless (instruction-stack instruction)
775          (sys::%format t "no stack information for instruction ~D~%"
776                        (instruction-opcode instruction))
777          (aver nil))))
778    (analyze-stack-path code 0 0)
779    (dolist (entry-point exception-entry-points)
780      ;; Stack depth is always 1 when handler is called.
781      (analyze-stack-path code (symbol-value entry-point) 1))
782    (let ((max-stack 0))
783      (declare (type fixnum max-stack))
784      (dotimes (i code-length)
785        (let* ((instruction (aref code i))
786               (instruction-depth (instruction-depth instruction)))
787          (when instruction-depth
788            (setf max-stack (max max-stack (the fixnum instruction-depth))))))
789      max-stack)))
790
791(defun analyze-locals (code)
792  (let ((code-length (length code))
793        (max-local 0))
794    (dotimes (i code-length max-local)
795      (let* ((instruction (aref code i))
796             (opcode (instruction-opcode instruction)))
797        (setf max-local
798              (max max-local
799                   (or (let ((opcode-register
800                                (jvm-opcode-register-used opcode)))
801                         (if (eq t opcode-register)
802                             (car (instruction-args instruction))
803                             opcode-register))
804                       0)))))))
805
806(defun delete-unused-labels (code handler-labels)
807  (declare (optimize speed))
808  (let ((code (coerce code 'vector))
809        (changed nil)
810        (marker (gensym)))
811    ;; Mark the labels that are actually branched to.
812    (dotimes (i (length code))
813      (let ((instruction (aref code i)))
814        (when (branch-p (instruction-opcode instruction))
815          (let ((label (car (instruction-args instruction))))
816            (set label marker)))))
817    ;; Add labels used for exception handlers.
818    (dolist (label handler-labels)
819      (set label marker))
820    ;; Remove labels that are not used as branch targets.
821    (dotimes (i (length code))
822      (let ((instruction (aref code i)))
823        (when (= (instruction-opcode instruction) 202) ; LABEL
824          (let ((label (car (instruction-args instruction))))
825            (declare (type symbol label))
826            (unless (eq (symbol-value label) marker)
827              (setf (aref code i) nil)
828              (setf changed t))))))
829    (values (if changed (delete nil code) code)
830            changed)))
831
832(defun delete-unreachable-code (code)
833  ;; Look for unreachable code after GOTO.
834  (declare (optimize speed))
835  (let* ((code (coerce code 'vector))
836         (changed nil)
837         (after-goto/areturn nil))
838    (dotimes (i (length code))
839      (declare (type (unsigned-byte 16) i))
840      (let* ((instruction (aref code i))
841             (opcode (instruction-opcode instruction)))
842        (cond (after-goto/areturn
843               (if (= opcode 202) ; LABEL
844                   (setf after-goto/areturn nil)
845                   ;; Unreachable.
846                   (progn
847                     (setf (aref code i) nil)
848                     (setf changed t))))
849              ((unconditional-control-transfer-p opcode)
850               (setf after-goto/areturn t)))))
851    (values (if changed (delete nil code) code)
852            changed)))
853
854
855(declaim (ftype (function (t) label-target-instructions) hash-labels))
856(defun label-target-instructions (code)
857  (let ((ht (make-hash-table :test 'eq))
858        (code (coerce code 'vector))
859        (pending-labels '()))
860    (dotimes (i (length code))
861      (let ((instruction (aref code i)))
862        (cond ((label-p instruction)
863               (push (instruction-label instruction) pending-labels))
864              (t
865               ;; Not a label.
866               (when pending-labels
867                 (dolist (label pending-labels)
868                   (setf (gethash label ht) instruction))
869                 (setf pending-labels nil))))))
870    ht))
871
872(defun optimize-jumps (code)
873  (declare (optimize speed))
874  (let* ((code (coerce code 'vector))
875         (ht (label-target-instructions code))
876         (changed nil))
877    (dotimes (i (length code))
878      (let* ((instruction (aref code i))
879             (opcode (and instruction (instruction-opcode instruction))))
880        (when (and opcode (branch-p opcode))
881          (let* ((target-label (car (instruction-args instruction)))
882                 (next-instruction (gethash1 target-label ht)))
883            (when next-instruction
884              (case (instruction-opcode next-instruction)
885                ((167 200)                  ;; GOTO
886                 (setf (instruction-args instruction)
887                       (instruction-args next-instruction)
888                       changed t))
889                (176 ; ARETURN
890                 (when (unconditional-control-transfer-p opcode)
891                   (setf (instruction-opcode instruction) 176
892                         (instruction-args instruction) nil
893                         changed t)))))))))
894    (values code changed)))
895
896
897(defun optimize-instruction-sequences (code)
898  (let* ((code (coerce code 'vector))
899         (changed nil))
900    (dotimes (i (1- (length code)))
901      (let* ((this-instruction (aref code i))
902             (this-opcode (and this-instruction
903                               (instruction-opcode this-instruction)))
904             (labels-skipped-p nil)
905             (next-instruction (do ((j (1+ i) (1+ j)))
906                                   ((or (>= j (length code))
907                                        (/= 202 ; LABEL
908                                            (instruction-opcode (aref code j))))
909                                    (when (< j (length code))
910                                      (aref code j)))
911                                 (setf labels-skipped-p t)))
912             (next-opcode (and next-instruction
913                               (instruction-opcode next-instruction))))
914        (case this-opcode
915          (205 ; CLEAR-VALUES
916           (when (eql next-opcode 205)       ; CLEAR-VALUES
917             (setf (aref code i) nil)
918             (setf changed t)))
919          (178 ; GETSTATIC
920           (when (and (eql next-opcode 87)   ; POP
921                      (not labels-skipped-p))
922             (setf (aref code i) nil)
923             (setf (aref code (1+ i)) nil)
924             (setf changed t)))
925          (176 ; ARETURN
926           (when (eql next-opcode 176)       ; ARETURN
927             (setf (aref code i) nil)
928             (setf changed t)))
929          ((200 167)                         ; GOTO GOTO_W
930           (when (and (or (eql next-opcode 202)  ; LABEL
931                          (eql next-opcode 200)  ; GOTO_W
932                          (eql next-opcode 167)) ; GOTO
933                      (eq (car (instruction-args this-instruction))
934                          (car (instruction-args next-instruction))))
935             (setf (aref code i) nil)
936             (setf changed t))))))
937    (values (if changed (delete nil code) code)
938            changed)))
939
940(defvar *enable-optimization* t)
941
942(defknown optimize-code (t t) t)
943(defun optimize-code (code handler-labels)
944  (unless *enable-optimization*
945    (format t "optimizations are disabled~%"))
946  (when *enable-optimization*
947    (when *compiler-debug*
948      (format t "----- before optimization -----~%")
949      (print-code code))
950    (loop
951       (let ((changed-p nil))
952         (multiple-value-setq
953             (code changed-p)
954           (delete-unused-labels code handler-labels))
955         (if changed-p
956             (setf code (optimize-instruction-sequences code))
957             (multiple-value-setq
958                 (code changed-p)
959               (optimize-instruction-sequences code)))
960         (if changed-p
961             (setf code (optimize-jumps code))
962             (multiple-value-setq
963                 (code changed-p)
964               (optimize-jumps code)))
965         (if changed-p
966             (setf code (delete-unreachable-code code))
967             (multiple-value-setq
968                 (code changed-p)
969               (delete-unreachable-code code)))
970         (unless changed-p
971           (return))))
972    (unless (vectorp code)
973      (setf code (coerce code 'vector)))
974    (when *compiler-debug*
975      (sys::%format t "----- after optimization -----~%")
976      (print-code code)))
977  code)
978
979
980
981
982(defun code-bytes (code)
983  (let ((length 0)
984        labels ;; alist
985        )
986    (declare (type (unsigned-byte 16) length))
987    ;; Pass 1: calculate label offsets and overall length.
988    (dotimes (i (length code))
989      (declare (type (unsigned-byte 16) i))
990      (let* ((instruction (aref code i))
991             (opcode (instruction-opcode instruction)))
992        (if (= opcode 202) ; LABEL
993            (let ((label (car (instruction-args instruction))))
994              (set label length)
995              (setf labels
996                    (acons label length labels)))
997            (incf length (opcode-size opcode)))))
998    ;; Pass 2: replace labels with calculated offsets.
999    (let ((index 0))
1000      (declare (type (unsigned-byte 16) index))
1001      (dotimes (i (length code))
1002        (declare (type (unsigned-byte 16) i))
1003        (let ((instruction (aref code i)))
1004          (when (branch-p (instruction-opcode instruction))
1005            (let* ((label (car (instruction-args instruction)))
1006                   (offset (- (the (unsigned-byte 16)
1007                                (symbol-value (the symbol label)))
1008                              index)))
1009              (setf (instruction-args instruction) (s2 offset))))
1010          (unless (= (instruction-opcode instruction) 202) ; LABEL
1011            (incf index (opcode-size (instruction-opcode instruction)))))))
1012    ;; Expand instructions into bytes, skipping LABEL pseudo-instructions.
1013    (let ((bytes (make-array length))
1014          (index 0))
1015      (declare (type (unsigned-byte 16) index))
1016      (dotimes (i (length code))
1017        (declare (type (unsigned-byte 16) i))
1018        (let ((instruction (aref code i)))
1019          (unless (= (instruction-opcode instruction) 202) ; LABEL
1020            (setf (svref bytes index) (instruction-opcode instruction))
1021            (incf index)
1022            (dolist (byte (instruction-args instruction))
1023              (setf (svref bytes index) byte)
1024              (incf index)))))
1025      (values bytes labels))))
1026
1027(defun finalize-code (code handler-labels optimize)
1028  (setf code (coerce (nreverse code) 'vector))
1029  (when optimize
1030    (setf code (optimize-code code handler-labels)))
1031  (resolve-instructions (expand-virtual-instructions code)))
1032
1033(provide '#:opcodes)
Note: See TracBrowser for help on using the repository browser.