source: branches/generic-class-file/abcl/src/org/armedbear/lisp/jvm-instructions.lisp @ 12876

Last change on this file since 12876 was 12876, checked in by ehuelsmann, 13 years ago

Move FINALIZE-CODE to jvm-instructions.lisp and make it
really finalize all code.

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