source: trunk/j/src/org/armedbear/lisp/jvm.lisp @ 8608

Last change on this file since 8608 was 8608, checked in by piso, 17 years ago

Work in progress (tested).

File size: 237.1 KB
Line 
1;;; jvm.lisp
2;;;
3;;; Copyright (C) 2003-2005 Peter Graves
4;;; $Id: jvm.lisp,v 1.400 2005-02-18 18:22:16 piso Exp $
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(in-package "EXT")
21
22(export 'defsubst)
23
24(in-package "JVM")
25
26(export '(compile-defun *catch-errors* jvm-compile jvm-compile-package))
27
28(import '(sys::%format
29          sys::source-transform
30          sys::define-source-transform
31          sys::expand-source-transform))
32
33(require '#:format)
34(require '#:clos)
35(require '#:source-transform)
36(require '#:opcodes)
37
38(shadow '(method variable))
39
40(defparameter *trust-user-type-declarations* t)
41
42(defvar *closure-variables* nil)
43
44(defvar *enable-dformat* nil)
45
46(defun dformat (destination control-string &rest args)
47  (when *enable-dformat*
48    (apply #'sys::%format destination control-string args)))
49
50(defun inline-expansion (name)
51  (sys:get-function-info-value name :inline-expansion))
52
53(defun (setf inline-expansion) (expansion name)
54  (sys:set-function-info-value name :inline-expansion expansion))
55
56;; Just an experiment...
57(defmacro defsubst (name lambda-list &rest body)
58  `(progn
59     (sys::%defun ',name ',lambda-list ',body)
60     (precompile ',name)
61     (setf (inline-expansion ',name)
62           (precompile-form (list* 'LAMBDA ',lambda-list ',body) t))
63     ',name))
64
65#+nil
66(defmacro defsubst (&rest args)
67  `(defun ,@args))
68
69(defvar *compiler-debug* nil)
70
71(defvar *pool* nil)
72(defvar *pool-count* 1)
73(defvar *pool-entries* nil)
74(defvar *fields* ())
75(defvar *static-code* ())
76
77(defvar *declared-symbols* nil)
78(defvar *declared-functions* nil)
79(defvar *declared-strings* nil)
80(defvar *declared-fixnums* nil)
81
82(defstruct (class-file (:constructor %make-class-file))
83  pathname ; pathname of output file
84  class
85  superclass
86  lambda-list ; as advertised
87  pool
88  (pool-count 1)
89  (pool-entries (make-hash-table :test #'equal))
90  fields
91  methods
92  static-code
93  (symbols (make-hash-table :test 'eq))
94  (functions (make-hash-table :test 'equal))
95  (strings (make-hash-table :test 'eq))
96  (fixnums (make-hash-table :test 'eql))
97  )
98
99(defun class-name-from-filespec (filespec)
100  (let* ((name (pathname-name filespec)))
101    (dotimes (i (length name))
102      (when (eql (char name i) #\-)
103        (setf (char name i) #\_)))
104    (concatenate 'string "org/armedbear/lisp/" name)))
105
106(defun make-class-file (&key pathname lambda-list)
107  (aver (not (null pathname)))
108  (let ((class-file (%make-class-file :pathname pathname
109                                      :lambda-list lambda-list)))
110    (setf (class-file-class class-file) (class-name-from-filespec pathname))
111    class-file))
112
113(defmacro with-class-file (class-file &body body)
114  (let ((var (gensym)))
115    `(let* ((,var ,class-file)
116            (*pool*               (class-file-pool ,var))
117            (*pool-count*         (class-file-pool-count ,var))
118            (*pool-entries*       (class-file-pool-entries ,var))
119            (*fields*             (class-file-fields ,var))
120            (*static-code*        (class-file-static-code ,var))
121            (*declared-symbols*   (class-file-symbols ,var))
122            (*declared-functions* (class-file-functions ,var))
123            (*declared-strings*   (class-file-strings ,var))
124            (*declared-fixnums*   (class-file-fixnums ,var)))
125       (progn ,@body)
126       (setf (class-file-pool ,var)         *pool*
127             (class-file-pool-count ,var)   *pool-count*
128             (class-file-pool-entries ,var) *pool-entries*
129             (class-file-fields ,var)       *fields*
130             (class-file-static-code ,var)  *static-code*
131             (class-file-symbols ,var)      *declared-symbols*
132             (class-file-functions ,var)    *declared-functions*
133             (class-file-strings ,var)      *declared-strings*
134             (class-file-fixnums ,var)      *declared-fixnums*
135             ))))
136
137(defstruct (compiland (:print-function print-compiland))
138  name
139  (kind :external) ; :INTERNAL or :EXTERNAL
140  lambda-expression
141  arg-vars
142  arity ; NIL if the number of args can vary.
143  p1-result
144  parent
145  (children 0) ; Number of local functions defined with FLET or LABELS.
146  argument-register
147  closure-register
148  class-file ; class-file object
149  (single-valued-p t)
150  )
151
152(defun print-compiland (compiland stream depth)
153  (%format stream "#<~S ~S>" 'compiland (compiland-name compiland)))
154
155(defvar *current-compiland* nil)
156
157(defvar *this-class* nil)
158
159(defvar *code* ())
160
161;; All tags visible at the current point of compilation, some of which may not
162;; be in the current compiland.
163(defvar *visible-tags* ())
164
165;; Next available register.
166(defvar *register* 0)
167
168;; Total number of registers allocated.
169(defvar *registers-allocated* 0)
170
171(defvar *handlers* ())
172
173(defstruct handler
174  from
175  to
176  code
177  catch-type)
178
179;; Variables visible at the current point of compilation.
180(defvar *visible-variables* ())
181
182;; All variables seen so far.
183(defvar *all-variables* ())
184
185;; Undefined variables that we've already warned about.
186(defvar *undefined-variables* ())
187
188(defvar *dump-variables* nil)
189
190(defun dump-1-variable (variable)
191  (%format t "  ~S special-p = ~S register = ~S index = ~S declared-type = ~S~%"
192           (variable-name variable)
193           (variable-special-p variable)
194           (variable-register variable)
195           (variable-index variable)
196           (variable-declared-type variable)))
197
198(defun dump-variables (list caption &optional (force nil))
199  (when (or force *dump-variables*)
200    (write-string caption)
201    (if list
202        (dolist (variable list)
203          (dump-1-variable variable))
204        (%format t "  None.~%"))))
205
206(defstruct variable
207  name
208  initform
209  temp-register
210  special-p
211  (declared-type t)
212  representation ; NIL (i.e. a LispObject reference) or :UNBOXED-FIXNUM
213  register ; register number or NIL
214  index
215  closure-index
216  (reads 0)
217  (writes 0)
218  used-non-locally-p
219  (compiland *current-compiland*))
220
221;; obj can be a symbol or variable
222;; returns variable or nil
223(defun unboxed-fixnum-variable (obj)
224  (cond ((symbolp obj)
225         (let ((variable (find-visible-variable obj)))
226           (if (and variable
227                    (eq (variable-representation variable) :unboxed-fixnum))
228               variable
229               nil)))
230        ((variable-p obj)
231         (if (eq (variable-representation obj) :unboxed-fixnum)
232             obj
233             nil))
234        (t
235         nil)))
236
237(defun arg-is-fixnum-p (arg)
238  (or (fixnump arg)
239      (unboxed-fixnum-variable arg)
240;;       (and (consp arg)
241;;            (eq (car arg) 'THE)
242;;            (subtypep (cadr arg) 'FIXNUM))
243      ))
244
245;; True for local functions defined with FLET or LABELS.
246(defvar *child-p* nil)
247
248(defvar *child-count* 0)
249
250(defun find-visible-variable (name)
251  (dolist (variable *visible-variables*)
252    (when (eq name (variable-name variable))
253      (return variable))))
254
255(defun unboxed-fixnum-variable-p (obj)
256;;   (let ((variable (and (symbolp obj)
257;;                        (find-visible-variable obj))))
258;;     (and variable
259;;          (eq (variable-representation variable) :unboxed-fixnum))))
260  (unboxed-fixnum-variable obj))
261
262(defun allocate-register ()
263  (let* ((register *register*)
264         (next-register (1+ register)))
265    (declare (type fixnum register next-register))
266    (setf *register* next-register)
267    (when (< *registers-allocated* next-register)
268      (setf *registers-allocated* next-register))
269    register))
270
271(defstruct local-function
272  name
273  compiland
274  function
275  class-file
276  variable)
277
278(defvar *local-functions* ())
279
280(defun find-local-function (name)
281  (find name *local-functions* :key #'local-function-name))
282
283(defvar *using-arg-array* nil)
284(defvar *hairy-arglist-p* nil)
285
286(defstruct node
287  ;; Block name or (TAGBODY) or (LET) or (MULTIPLE-VALUE-BIND).
288  name
289  form
290  (compiland *current-compiland*))
291
292;; Used to wrap TAGBODYs, UNWIND-PROTECTs and LET/LET*/M-V-B forms as well as
293;; BLOCKs per se.
294(defstruct (block-node (:conc-name block-) (:include node))
295  (exit (gensym))
296  target
297  catch-tag
298  ;; True if there is any RETURN from this block.
299  return-p
300  ;; True if there is a non-local RETURN from this block.
301  non-local-return-p
302  ;; True if a tag in this tagbody is the target of a non-local GO.
303  non-local-go-p
304  ;; If non-nil, register containing saved dynamic environment for this block.
305  environment-register
306  ;; Only used in LET/LET*/M-V-B nodes.
307  vars
308  free-specials
309  )
310
311(defun node-constant-p (object)
312  (cond ((block-node-p object)
313         nil)
314        ((constantp object)
315         t)
316        (t
317         nil)))
318
319(defvar *blocks* ())
320
321(defun find-block (name)
322  (dolist (block *blocks*)
323    (when (eq name (block-name block))
324      (return block))))
325
326(defstruct tag
327  name
328  label
329  block
330  (compiland *current-compiland*))
331
332;;; Pass 1.
333
334;; Returns a list of declared free specials, if any are found.
335(defun process-declarations-for-vars (body vars)
336  (let ((free-specials '()))
337    (dolist (subform body)
338      (unless (and (consp subform) (eq (car subform) 'DECLARE))
339        (return))
340      (let ((decls (cdr subform)))
341        (dolist (decl decls)
342          (case (car decl)
343            ((DYNAMIC-EXTENT FTYPE IGNORE IGNORABLE INLINE NOTINLINE OPTIMIZE)
344             ;; Nothing to do here.
345             )
346            (SPECIAL
347             (dolist (sym (cdr decl))
348               (let ((variable (find sym vars :key #'variable-name)))
349                 (cond (variable
350                        (setf (variable-special-p variable) t))
351                       (t
352                        (dformat t "adding free special ~S~%" sym)
353                        (push (make-variable :name sym :special-p t) free-specials))))))
354            (TYPE
355             (dolist (sym (cddr decl))
356               (dolist (variable vars)
357                 (when (eq sym (variable-name variable))
358                   (setf (variable-declared-type variable) (cadr decl))))))
359            (t
360             (dolist (sym (cdr decl))
361               (dolist (variable vars)
362                 (when (eq sym (variable-name variable))
363                   (setf (variable-declared-type variable) (car decl))))))))))
364    free-specials))
365
366(defun p1-let-vars (varlist)
367  (let ((vars ()))
368    (dolist (varspec varlist)
369      (cond ((consp varspec)
370             (let ((name (car varspec))
371                   (initform (p1 (cadr varspec))))
372               (push (make-variable :name name :initform initform) vars)))
373            (t
374             (push (make-variable :name varspec) vars))))
375    (setf vars (nreverse vars))
376    (dolist (variable vars)
377      (push variable *visible-variables*)
378      (push variable *all-variables*))
379    vars))
380
381(defun p1-let*-vars (varlist)
382  (let ((vars ()))
383    (dolist (varspec varlist)
384      (cond ((consp varspec)
385             (let* ((name (car varspec))
386                    (initform (p1 (cadr varspec)))
387                    (var (make-variable :name name :initform initform)))
388               (push var vars)
389               (push var *visible-variables*)
390               (push var *all-variables*)))
391            (t
392             (let ((var (make-variable :name varspec)))
393               (push var vars)
394               (push var *visible-variables*)
395               (push var *all-variables*)))))
396    (nreverse vars)))
397
398(defun p1-let/let* (form)
399  (let* ((*visible-variables* *visible-variables*)
400         (block (make-block-node :name '(LET)))
401         (*blocks* (cons block *blocks*))
402         (op (car form))
403         (varlist (cadr form))
404         (body (cddr form)))
405    (aver (or (eq op 'LET) (eq op 'LET*)))
406    (when (eq op 'LET)
407      ;; Convert to LET* if possible.
408      (dolist (varspec varlist (setf op 'LET*))
409        (or (atom varspec)
410            (constantp (cadr varspec))
411            (eq (car varspec) (cadr varspec))
412            (return nil))))
413    (let ((vars (if (eq op 'LET) (p1-let-vars varlist) (p1-let*-vars varlist))))
414      (dformat t "p1-let/let* vars = ~S~%" (mapcar #'variable-name vars))
415      ;; Check for globally declared specials.
416      (dolist (variable vars)
417        (when (special-variable-p (variable-name variable))
418          (setf (variable-special-p variable) t)))
419      (setf (block-free-specials block) (process-declarations-for-vars body vars))
420      (setf (block-vars block) vars))
421    (setf body (mapcar #'p1 body))
422    (setf (block-form block) (list* op varlist body))
423    block))
424
425(defun p1-m-v-b (form)
426;;   (dformat t "p1-multiple-value-bind~%")
427  (when (= (length (cadr form)) 1)
428    (let ((new-form `(let ((,(caadr form) ,(caddr form))) ,@(cdddr form))))
429      (dformat t "old form = ~S~%" form)
430      (dformat t "new-form = ~S~%" new-form)
431      (return-from p1-m-v-b (p1-let/let* new-form))))
432  (let* ((*visible-variables* *visible-variables*)
433         (block (make-block-node :name '(MULTIPLE-VALUE-BIND)))
434         (*blocks* (cons block *blocks*))
435         (varlist (cadr form))
436         (values-form (caddr form))
437         (body (cdddr form)))
438    ;; Process the values-form first. ("The scopes of the name binding and
439    ;; declarations do not include the values-form.")
440    (setf values-form (p1 values-form))
441    (let ((vars ()))
442      (dolist (symbol varlist)
443        (let ((var (make-variable :name symbol)))
444          (push var vars)
445          (push var *visible-variables*)
446          (push var *all-variables*)))
447      ;; Check for globally declared specials.
448      (dolist (variable vars)
449        (when (special-variable-p (variable-name variable))
450          (setf (variable-special-p variable) t)))
451      (setf (block-free-specials block) (process-declarations-for-vars body vars))
452      (setf (block-vars block) (nreverse vars)))
453    (setf body (mapcar #'p1 body))
454    (setf (block-form block) (list* 'MULTIPLE-VALUE-BIND varlist values-form body))
455    block))
456
457(defun p1-block (form)
458  (let* ((block (make-block-node :name (cadr form)))
459         (*blocks* (cons block *blocks*)))
460    (setf (block-form block) (list* 'BLOCK (cadr form) (mapcar #'p1 (cddr form))))
461    block))
462
463(defun p1-unwind-protect (form)
464  (let* ((block (make-block-node :name '(UNWIND-PROTECT)))
465         (*blocks* (cons block *blocks*)))
466    (setf (block-form block) (list* 'UNWIND-PROTECT (mapcar #'p1 (cdr form))))
467    block))
468
469(defun p1-return-from (form)
470  (let* ((name (second form))
471         (block (find-block name)))
472    (when (null block)
473      (compiler-error "RETURN-FROM ~S: no block named ~S is currently visible."
474                      name name))
475    (dformat t "p1-return-from block = ~S~%" (block-name block))
476    (setf (block-return-p block) t)
477    (cond ((eq (block-compiland block) *current-compiland*)
478           ;; Local case. If the RETURN is nested inside an UNWIND-PROTECT
479           ;; which is inside the block we're returning from, we'll do a non-
480           ;; local return anyway so that UNWIND-PROTECT can catch it and run
481           ;; its cleanup forms.
482           (dformat t "*blocks* = ~S~%" (mapcar #'block-name *blocks*))
483           (let ((protected
484                  (dolist (enclosing-block *blocks*)
485                    (when (eq enclosing-block block)
486                      (return nil))
487                    (when (equal (block-name enclosing-block) '(UNWIND-PROTECT))
488                      (return t)))))
489             (dformat t "p1-return-from protected = ~S~%" protected)
490             (when protected
491               (setf (block-non-local-return-p block) t))))
492          (t
493           (setf (block-non-local-return-p block) t)))
494    (when (block-non-local-return-p block)
495      (dformat t "non-local return from block ~S~%" (block-name block))))
496  (list* 'RETURN-FROM (cadr form) (mapcar #'p1 (cddr form))))
497
498(defun p1-tagbody (form)
499  (let* ((block (make-block-node :name '(TAGBODY)))
500         (*blocks* (cons block *blocks*))
501         (*visible-tags* *visible-tags*)
502         (body (cdr form)))
503    ;; Make all the tags visible before processing the body forms.
504    (dolist (subform body)
505      (when (or (symbolp subform) (integerp subform))
506        (let* ((tag (make-tag :name subform :label (gensym) :block block)))
507          (push tag *visible-tags*))))
508    (let ((new-body '()))
509      (dolist (subform body)
510        (push (if (or (symbolp subform) (integerp subform))
511                  subform
512                  (p1 subform))
513              new-body))
514      (setf (block-form block) (list* 'TAGBODY (nreverse new-body))))
515    block))
516
517(defun p1-go (form)
518  (let* ((name (cadr form))
519         (tag (find-tag name)))
520    (unless tag
521      (error "p1-go: tag not found: ~S" name))
522    (let ((tag-block (tag-block tag)))
523      (cond ((eq (tag-compiland tag) *current-compiland*)
524             ;; Does the GO leave an enclosing UNWIND-PROTECT?
525             (let ((protected
526                    (dolist (enclosing-block *blocks*)
527                      (when (eq enclosing-block tag-block)
528                        (return nil))
529                      (when (equal (block-name enclosing-block) '(UNWIND-PROTECT))
530                        (return t)))))
531               (when protected
532                 (setf (block-non-local-go-p tag-block) t))))
533            (t
534             (setf (block-non-local-go-p tag-block) t)))))
535  form)
536
537(defun p1-flet (form)
538  (incf (compiland-children *current-compiland*) (length (cadr form)))
539  (let ((*current-compiland* *current-compiland*)
540        (compilands '()))
541    (dolist (definition (cadr form))
542      (let ((name (car definition)))
543        ;; FIXME
544        (when (and (consp name) (eq (car name) 'SETF))
545          (compiler-unsupported "P1-FLET: can't handle ~S." name))
546        (let* ((lambda-list (cadr definition))
547               (body (cddr definition))
548               (compiland (make-compiland :name name
549                                          :parent *current-compiland*)))
550          (multiple-value-bind (body decls)
551            (sys::parse-body body)
552            (setf (compiland-lambda-expression compiland)
553                  `(lambda ,lambda-list ,@decls (block ,name ,@body)))
554            (let ((*visible-variables* *visible-variables*)
555                  (*current-compiland* compiland))
556              (p1-compiland compiland)))
557          (push compiland compilands))))
558  (list* (car form) (nreverse compilands) (mapcar #'p1 (cddr form)))))
559
560(defun p1-labels (form)
561  (incf (compiland-children *current-compiland*) (length (cadr form)))
562  (let ((*visible-variables* *visible-variables*)
563        (*local-functions* *local-functions*)
564        (*current-compiland* *current-compiland*)
565        (local-functions ()))
566    (dolist (definition (cadr form))
567      (let ((name (car definition)))
568        ;; FIXME
569        (when (and (consp name) (eq (car name) 'SETF))
570          (compiler-unsupported "P1-LABELS: can't handle ~S." name))
571        (let* ((lambda-list (cadr definition))
572               (body (cddr definition))
573               (compiland (make-compiland :name name
574                                          :parent *current-compiland*))
575               (variable (make-variable :name (copy-symbol name)))
576               (local-function (make-local-function :name name
577                                                    :compiland compiland
578                                                    :variable variable)))
579          (multiple-value-bind (body decls)
580            (sys::parse-body body)
581            (setf (compiland-lambda-expression compiland)
582                  `(lambda ,lambda-list ,@decls (block ,name ,@body))))
583          (push variable *all-variables*)
584          (push local-function local-functions))))
585    (setf local-functions (nreverse local-functions))
586    ;; Make the local functions visible.
587    (dolist (local-function local-functions)
588      (push local-function *local-functions*)
589      (push (local-function-variable local-function) *visible-variables*))
590    (dolist (local-function local-functions)
591      (let ((*visible-variables* *visible-variables*)
592            (*current-compiland* (local-function-compiland local-function)))
593        (p1-compiland (local-function-compiland local-function))))
594    (list* (car form) local-functions (mapcar #'p1 (cddr form)))))
595
596(defun p1-function (form)
597  (let (local-function)
598    (cond ((and (consp (cadr form)) (eq (caadr form) 'LAMBDA))
599           (when *current-compiland*
600             (incf (compiland-children *current-compiland*)))
601           (let* ((*current-compiland* *current-compiland*)
602                  (lambda-form (cadr form))
603                  (lambda-list (cadr lambda-form))
604                  (body (cddr lambda-form))
605                  (compiland (make-compiland :name (gensym "ANONYMOUS-LAMBDA-")
606                                             :lambda-expression lambda-form
607                                             :parent *current-compiland*)))
608             (multiple-value-bind (body decls)
609               (sys::parse-body body)
610               (setf (compiland-lambda-expression compiland)
611                     `(lambda ,lambda-list ,@decls (block nil ,@body)))
612               (let ((*visible-variables* *visible-variables*)
613                     (*current-compiland* compiland))
614                 (p1-compiland compiland)))
615             (list 'FUNCTION compiland)))
616          ((setf local-function (find-local-function (cadr form)))
617           (dformat t "p1-function local function ~S~%" (cadr form))
618           (let ((variable (local-function-variable local-function)))
619             (when variable
620               (unless (or (eq (variable-compiland variable) *current-compiland*)
621                           (eq (local-function-compiland local-function) *current-compiland*))
622                 (dformat t "p1-function ~S used non-locally~%" (variable-name variable))
623                 (setf (variable-used-non-locally-p variable) t))))
624           form)
625          (t
626           form))))
627
628(defun p1-lambda (form)
629  (let* ((lambda-list (cadr form))
630         (body (cddr form))
631         (auxvars (memq '&AUX lambda-list)))
632    (when auxvars
633      (setf lambda-list (subseq lambda-list 0 (position '&AUX lambda-list)))
634      (setf body (list (append (list 'LET* (cdr auxvars)) body))))
635    (p1-function (list 'FUNCTION (list* 'LAMBDA lambda-list body)))))
636
637(defun p1-eval-when (form)
638  (list* (car form) (cadr form) (mapcar #'p1 (cddr form))))
639
640(defun p1-quote (form)
641  (if (numberp (second form))
642      (second form)
643      form))
644
645(defun p1-setq (form)
646  (unless (= (length form) 3)
647    (error "Too many arguments for SETQ."))
648  (let ((arg1 (second form))
649        (arg2 (third form)))
650    (let ((variable (find-visible-variable arg1)))
651      (if variable
652          (progn
653            (incf (variable-writes variable))
654            (cond ((eq (variable-compiland variable) *current-compiland*)
655                   (dformat t "p1-setq: write ~S~%" arg1))
656                  (t
657                   (dformat t "p1-setq: non-local write ~S~%" arg1)
658                   (setf (variable-used-non-locally-p variable) t))))
659          (dformat t "p1-setq: unknown variable ~S~%" arg1)))
660    (list 'SETQ arg1 (p1 arg2))))
661
662(defun p1-the (form)
663  (dformat t "p1-the form = ~S~%" form)
664  (let ((type (second form))
665        (expr (third form)))
666    (cond ((and (listp type) (eq (car type) 'VALUES))
667           ;; FIXME
668           (p1 expr))
669          ((= *safety* 3)
670           (dformat t "p1-the expr = ~S~%" expr)
671           (let* ((sym (gensym))
672                  (new-expr
673                   `(let ((,sym ,expr))
674                      (sys::require-type ,sym ',type)
675                      ,sym)))
676             (dformat t "p1-the new-expr = ~S~%" new-expr)
677             (p1 new-expr)))
678          (t
679           (dformat t "p1-the t case expr = ~S~%" expr)
680           (if (subtypep type 'FIXNUM)
681               (list 'THE type (p1 expr))
682               (p1 expr))))))
683
684(defun p1-default (form)
685  (list* (car form) (mapcar #'p1 (cdr form))))
686
687(defun p1-throw (form)
688  (let ((new-form (rewrite-throw form)))
689    (when (neq new-form form)
690      (return-from p1-throw (p1 new-form))))
691  (list* 'THROW (mapcar #'p1 (cdr form))))
692
693(defun expand-inline (form expansion)
694  (let ((args (cdr form))
695        (vars (cadr expansion))
696        (varlist ())
697        new-form)
698    (do ((vars vars (cdr vars))
699         (args args (cdr args)))
700        ((null vars))
701      (push (list (car vars) (car args)) varlist))
702    (setf varlist (nreverse varlist))
703    (setf new-form (list* 'LET varlist (cddr expansion)))
704    new-form))
705
706(defun p1-function-call (form)
707  (let ((op (car form)))
708    (let ((new-form (rewrite-function-call form)))
709      (when (neq new-form form)
710        (dformat t "old form = ~S~%" form)
711        (dformat t "new form = ~S~%" new-form)
712        (return-from p1-function-call (p1 new-form))))
713    (let ((source-transform (source-transform op)))
714      (when source-transform
715        (let ((new-form (expand-source-transform form)))
716          (when (neq new-form form)
717            (return-from p1-function-call (p1 new-form))))))
718    (let ((expansion (inline-expansion op)))
719      (when expansion
720        (return-from p1-function-call (p1 (expand-inline form expansion)))))
721    (let ((local-function (find-local-function op)))
722      (cond (local-function
723             (dformat t "p1 local function ~S~%" op)
724
725             ;; FIXME
726             (dformat t "local function assumed not single-valued~%")
727             (setf (compiland-single-valued-p *current-compiland*) nil)
728
729             (unless (eq (local-function-compiland local-function)
730                         *current-compiland*)
731               (let ((variable (local-function-variable local-function)))
732                 (when variable
733                   (unless (eq (variable-compiland variable) *current-compiland*)
734                     (dformat t "p1 ~S used non-locally~%" (variable-name variable))
735                     (setf (variable-used-non-locally-p variable) t))))))
736            (t
737             ;; Not a local function call.
738             (unless (single-valued-p op)
739               (%format t "not single-valued op = ~S~%" op)
740               (setf (compiland-single-valued-p *current-compiland*) nil)))))
741    (list* op (mapcar #'p1 (cdr form)))))
742
743(defun p1 (form)
744  (cond ((symbolp form)
745         (cond ((constantp form) ; a DEFCONSTANT
746                (let ((value (symbol-value form)))
747                  (if (numberp value)
748                      value
749                      form)))
750               ((keywordp form)
751                form)
752               (t
753                (let ((variable (find-visible-variable form)))
754                  (if variable
755                      (progn
756                        (incf (variable-reads variable))
757                        (cond
758                         ((eq (variable-compiland variable) *current-compiland*)
759                          (dformat t "p1: read ~S~%" form))
760                         (t
761                          (dformat t "p1: non-local read ~S variable-compiland = ~S current compiland = ~S~%"
762                                   form
763                                   (compiland-name (variable-compiland variable))
764                                   (compiland-name *current-compiland*))
765                          (setf (variable-used-non-locally-p variable) t))))
766                      (dformat t "p1: unknown variable ~S~%" form)))
767                form)))
768        ((atom form)
769         form)
770        (t
771         (let ((op (car form))
772               handler)
773           (cond ((symbolp op)
774                  (cond ((setf handler (get op 'p1-handler))
775                         (funcall handler form))
776                        ((macro-function op)
777                         (p1 (macroexpand form)))
778                        ((special-operator-p op)
779                         (compiler-unsupported "P1: unsupported special operator ~S" op))
780                        (t
781                         (p1-function-call form))))
782                 ((and (consp op) (eq (car op) 'LAMBDA))
783                  (p1 (list* 'FUNCALL form)))
784                 (t
785                  form))))))
786
787(defun install-p1-handler (symbol handler)
788  (setf (get symbol 'p1-handler) handler))
789
790(install-p1-handler 'block                'p1-block)
791(install-p1-handler 'catch                'p1-default)
792(install-p1-handler 'declare              'identity)
793(install-p1-handler 'eval-when            'p1-eval-when)
794(install-p1-handler 'flet                 'p1-flet)
795(install-p1-handler 'function             'p1-function)
796(install-p1-handler 'go                   'p1-go)
797(install-p1-handler 'if                   'p1-default)
798(install-p1-handler 'labels               'p1-labels)
799(install-p1-handler 'lambda               'p1-lambda)
800(install-p1-handler 'let                  'p1-let/let*)
801(install-p1-handler 'let*                 'p1-let/let*)
802(install-p1-handler 'load-time-value      'identity)
803(install-p1-handler 'locally              'p1-default)
804(install-p1-handler 'multiple-value-bind  'p1-m-v-b)
805(install-p1-handler 'multiple-value-call  'p1-default)
806(install-p1-handler 'multiple-value-list  'p1-default)
807(install-p1-handler 'multiple-value-prog1 'p1-default)
808(install-p1-handler 'progn                'p1-default)
809(install-p1-handler 'progv                'identity)
810(install-p1-handler 'quote                'p1-quote)
811(install-p1-handler 'return-from          'p1-return-from)
812(install-p1-handler 'setq                 'p1-setq)
813(install-p1-handler 'symbol-macrolet      'identity)
814(install-p1-handler 'tagbody              'p1-tagbody)
815(install-p1-handler 'the                  'p1-the)
816(install-p1-handler 'throw                'p1-throw)
817(install-p1-handler 'unwind-protect       'p1-unwind-protect)
818
819(defun dump-pool ()
820  (let ((pool (reverse *pool*))
821        entry type)
822    (dotimes (index (1- *pool-count*))
823      (setq entry (car pool))
824      (setq type (case (car entry)
825                   (7 'class)
826                   (9 'field)
827                   (10 'method)
828                   (11 'interface)
829                   (8 'string)
830                   (3 'integer)
831                   (4 'float)
832                   (5 'long)
833                   (6 'double)
834                   (12 'name-and-type)
835                   (1 'utf8)))
836      (%format t "~D: ~A ~S~%" (1+ index) type entry)
837      (setq pool (cdr pool))))
838  t)
839
840(defun pool-get (entry)
841  (declare (optimize speed))
842  (let ((index (gethash entry *pool-entries*)))
843    (unless index
844      (setf index *pool-count*)
845      (push entry *pool*)
846      (setf (gethash entry *pool-entries*) index)
847      (setf *pool-count* (1+ index)))
848    index))
849
850(defun pool-name (name)
851  (declare (optimize speed))
852  (pool-get (list 1 (length name) name)))
853
854(defun pool-name-and-type (name type)
855  (declare (optimize speed))
856  (pool-get (list 12
857                  (pool-name name)
858                  (pool-name type))))
859
860;; Assumes CLASS-NAME is already in the correct form ("org/armedbear/lisp/Lisp"
861;; as opposed to "org.armedbear.lisp.Lisp").
862(defun pool-class (class-name)
863  (declare (optimize speed))
864  (pool-get (list 7 (pool-name class-name))))
865
866;; (tag class-index name-and-type-index)
867(defun pool-field (class-name field-name type-name)
868  (declare (optimize speed))
869  (pool-get (list 9
870                  (pool-class class-name)
871                  (pool-name-and-type field-name type-name))))
872
873;; (tag class-index name-and-type-index)
874(defun pool-method (class-name method-name type-name)
875  (declare (optimize speed))
876  (pool-get (list 10
877                  (pool-class class-name)
878                  (pool-name-and-type method-name type-name))))
879
880(defun pool-string (string)
881  (declare (optimize speed))
882  (pool-get (list 8 (pool-name string))))
883
884(defun pool-int (n)
885  (declare (optimize speed))
886  (pool-get (list 3 n)))
887
888(defun u2 (n)
889  (declare (optimize speed))
890  (declare (type fixnum n))
891  (list (logand (ash n -8) #xff)
892        (logand n #xff)))
893
894(locally (declare (optimize speed))
895  (defstruct (instruction
896              (:constructor make-instruction (opcode args)))
897    opcode
898    args
899    stack
900    depth))
901
902(defun print-instruction (instruction)
903  (%format nil "~A ~A stack = ~S depth = ~S"
904          (opcode-name (instruction-opcode instruction))
905          (instruction-args instruction)
906          (instruction-stack instruction)
907          (instruction-depth instruction)))
908
909(defun inst (instr &optional args)
910  (declare (optimize speed))
911  (let ((opcode (if (numberp instr)
912                    instr
913                    (opcode-number instr))))
914    (unless (listp args)
915      (setf args (list args)))
916    (make-instruction opcode args)))
917
918(defun emit (instr &rest args)
919  (declare (optimize speed))
920  (let ((instruction (inst instr args)))
921    (push instruction *code*)
922    instruction))
923
924(defun label (symbol)
925  (declare (optimize speed))
926  (emit 'label symbol)
927  (setf (symbol-value symbol) nil))
928
929(defconstant +java-string+ "Ljava/lang/String;")
930(defconstant +lisp-class+ "org/armedbear/lisp/Lisp")
931(defconstant +lisp-object-class+ "org/armedbear/lisp/LispObject")
932(defconstant +lisp-object+ "Lorg/armedbear/lisp/LispObject;")
933(defconstant +lisp-object-array+ "[Lorg/armedbear/lisp/LispObject;")
934(defconstant +lisp-string+ "Lorg/armedbear/lisp/SimpleString;")
935(defconstant +lisp-symbol-class+ "org/armedbear/lisp/Symbol")
936(defconstant +lisp-symbol+ "Lorg/armedbear/lisp/Symbol;")
937(defconstant +lisp-thread-class+ "org/armedbear/lisp/LispThread")
938(defconstant +lisp-thread+ "Lorg/armedbear/lisp/LispThread;")
939(defconstant +lisp-cons-class+ "org/armedbear/lisp/Cons")
940(defconstant +lisp-cons+ "Lorg/armedbear/lisp/Cons;")
941(defconstant +lisp-fixnum-class+ "org/armedbear/lisp/Fixnum")
942(defconstant +lisp-fixnum+ "Lorg/armedbear/lisp/Fixnum;")
943(defconstant +lisp-simple-string-class+ "org/armedbear/lisp/SimpleString")
944(defconstant +lisp-simple-string+ "Lorg/armedbear/lisp/SimpleString;")
945(defconstant +lisp-environment+ "Lorg/armedbear/lisp/Environment;")
946(defconstant +lisp-binding+ "Lorg/armedbear/lisp/Binding;")
947(defconstant +lisp-throw-class+ "org/armedbear/lisp/Throw")
948(defconstant +lisp-return-class+ "org/armedbear/lisp/Return")
949(defconstant +lisp-go-class+ "org/armedbear/lisp/Go")
950(defconstant +lisp-ctf-class+ "org/armedbear/lisp/ClosureTemplateFunction")
951(defconstant +lisp-compiled-closure-class+ "org/armedbear/lisp/CompiledClosure")
952(defconstant +lisp-compiled-function-class+ "org/armedbear/lisp/CompiledFunction")
953(defconstant +lisp-primitive-class+ "org/armedbear/lisp/Primitive")
954
955(defsubst emit-push-nil ()
956  (emit 'getstatic +lisp-class+ "NIL" +lisp-object+))
957
958(defsubst emit-push-t ()
959  (emit 'getstatic +lisp-class+ "T" +lisp-symbol+))
960
961(defun emit-push-constant-int (n)
962  (if (<= -32768 n 32767)
963      (emit 'sipush n)
964      (emit 'ldc (pool-int n))))
965
966(defun make-descriptor-info (arg-types return-type)
967  (let ((descriptor (with-output-to-string (s)
968                      (princ #\( s)
969                      (dolist (type arg-types)
970                        (princ type s))
971                      (princ #\) s)
972                      (princ (or return-type "V") s)))
973        (stack-effect (let ((result (cond ((null return-type) 0)
974                                          ((equal return-type "J") 2)
975                                          (t 1))))
976                        (dolist (type arg-types result)
977                          (decf result (if (equal type "J") 2 1))))))
978    (cons descriptor stack-effect)))
979
980(defparameter *descriptors* (make-hash-table :test #'equal))
981
982(defun get-descriptor-info (arg-types return-type)
983  (let* ((key (list arg-types return-type))
984         (descriptor-info (gethash key *descriptors*)))
985    (or descriptor-info
986        (setf (gethash key *descriptors*)
987              (make-descriptor-info arg-types return-type)))))
988
989(defsubst get-descriptor (arg-types return-type)
990  (car (get-descriptor-info arg-types return-type)))
991
992(defun emit-invokestatic (class-name method-name arg-types return-type)
993  (let* ((info (get-descriptor-info arg-types return-type))
994         (descriptor (car info))
995         (stack-effect (cdr info))
996         (instruction (emit 'invokestatic class-name method-name descriptor)))
997    (setf (instruction-stack instruction) stack-effect)))
998
999(defun emit-invokevirtual (class-name method-name arg-types return-type)
1000  (let* ((info (get-descriptor-info arg-types return-type))
1001         (descriptor (car info))
1002         (stack-effect (cdr info))
1003         (instruction (emit 'invokevirtual class-name method-name descriptor)))
1004    (setf (instruction-stack instruction) (1- stack-effect))))
1005
1006(defun emit-invokespecial-init (class-name arg-types)
1007  (let* ((info (get-descriptor-info arg-types nil))
1008         (descriptor (car info))
1009         (stack-effect (cdr info))
1010         (instruction (emit 'invokespecial class-name "<init>" descriptor)))
1011    (setf (instruction-stack instruction) (1- stack-effect))))
1012
1013;; Index of local variable used to hold the current thread.
1014(defvar *thread* nil)
1015
1016(defvar *initialize-thread-var* nil)
1017
1018(defun maybe-initialize-thread-var ()
1019  (when *initialize-thread-var*
1020    (emit-invokestatic +lisp-thread-class+ "currentThread" nil +lisp-thread+)
1021    (emit 'astore *thread*)))
1022
1023(defsubst ensure-thread-var-initialized ()
1024  (setf *initialize-thread-var* t))
1025
1026(defun emit-push-current-thread ()
1027  (declare (optimize speed))
1028  (ensure-thread-var-initialized)
1029  (emit 'aload *thread*))
1030
1031(defun generate-arg-count-check (arity)
1032  (aver (fixnump arity))
1033  (aver (not (minusp arity)))
1034  (aver (not (null (compiland-argument-register *current-compiland*))))
1035  (let ((label1 (gensym)))
1036    (emit 'aload (compiland-argument-register *current-compiland*))
1037    (emit 'arraylength)
1038    (emit 'bipush arity)
1039    (emit 'if_icmpeq `,label1)
1040    (emit 'aload 0) ; this
1041    (emit-invokevirtual *this-class* "argCountError" nil nil)
1042    (emit 'label `,label1)))
1043
1044(defun maybe-generate-interrupt-check ()
1045  (unless (> *speed* *safety*)
1046    (let ((label1 (gensym)))
1047      (emit 'getstatic +lisp-class+ "interrupted" "Z")
1048      (emit 'ifeq `,label1)
1049      (emit-invokestatic +lisp-class+ "handleInterrupt" nil nil)
1050      (emit 'label `,label1))))
1051
1052(defun single-valued-p-init ()
1053  (dolist (op '(+ - * /
1054                1+ 1- < > <= >= = /=
1055                car cdr caar cadr cdar cddr cadar caddr cdddr cddddr
1056                first second third
1057                eq eql equal equalp
1058                length
1059                constantp symbolp
1060                list list*
1061                macro-function
1062                compiler-macro-function
1063                sys::%defun
1064                get
1065                atom
1066                compiled-function-p
1067                fdefinition
1068                special-operator-p keywordp functionp fboundp zerop consp listp
1069                numberp integerp floatp
1070                plusp minusp
1071                complexp arrayp readtablep packagep
1072                array-dimensions array-rank array-total-size
1073                array-element-type upgraded-array-element-type
1074                simple-vector-p simple-string-p bit-vector-p simple-bit-vector-p
1075                stringp
1076                row-major-aref
1077                quote function
1078                mapcar
1079                find position
1080                append nconc subseq adjoin
1081                revappend nreconc
1082                copy-seq
1083                assoc assoc-if assoc-if-not acons assq assql
1084                char-code code-char char-int digit-char-p
1085                member ext:memq
1086                remove remove-if remove-if-not delete delete-if delete-if-not
1087                special-variable-p
1088                gensym
1089                symbol-name symbol-function
1090                coerce
1091                reverse nreverse
1092                last
1093                cons rplaca rplacd
1094                sys::%rplaca sys::%rplacd
1095                copy-list copy-tree
1096                make-sequence make-list make-array make-package make-hash-table
1097                make-string
1098                find-package
1099                pathname make-pathname pathname-name directory
1100                package-used-by-list package-shadowing-symbols
1101                nthcdr
1102                aref elt
1103                not null endp
1104                concatenate
1105                format sys::%format
1106                prin1 princ print write
1107                compute-restarts find-restart restart-name
1108                string
1109                string=
1110                setq
1111                multiple-value-list push pop
1112                type-of class-of
1113                typep sys::%typep
1114                abs
1115                ash
1116                float-radix
1117                logand logandc1 logandc2 logeqv logior lognand
1118                lognot logorc1 logorc2 logxor
1119                logbitp
1120                slot-boundp slot-value slot-exists-p
1121                allocate-instance
1122                find-class
1123                class-name
1124                constantly
1125                exp expt log
1126                min max
1127                realpart imagpart
1128                integer-length
1129                sqrt isqrt gcd lcm signum
1130                char schar
1131                open
1132                svref
1133                fill-pointer
1134                symbol-value symbol-package package-name
1135                fourth
1136                vector-push vector-push-extend
1137                union nunion
1138                remove-duplicates delete-duplicates
1139                read-byte
1140                fresh-line terpri
1141                lambda
1142                ext:classp
1143                ext:fixnump
1144                ext:memql
1145                sys::generic-function-name
1146                sys::puthash
1147                precompiler::precompile1
1148                declare
1149                go
1150                sys::%structure-ref
1151                inst
1152                emit
1153                label
1154                maybe-emit-clear-values
1155                single-valued-p
1156                sys:single-valued-p
1157                sys:write-8-bits
1158                sys::require-type
1159                ))
1160    (setf (sys:single-valued-p op) t)))
1161
1162(eval-when (:load-toplevel :execute)
1163  (single-valued-p-init))
1164
1165(defun single-valued-p (form)
1166  (cond ((block-node-p form)
1167         (if (equal (block-name form) '(TAGBODY))
1168             t
1169             (single-valued-p (node-form form))))
1170        ((atom form)
1171         t)
1172        ((eq (first form) 'IF)
1173         (and ;;(single-valued-p (second form))
1174              (single-valued-p (third form))
1175              (single-valued-p (fourth form))))
1176        ((eq (first form) 'PROGN)
1177         (single-valued-p (car (last form))))
1178        ((memq (first form) '(LET LET*))
1179         (single-valued-p (car (last (cddr form)))))
1180        ((memq (car form) '(AND OR))
1181         (every #'single-valued-p (cdr form)))
1182        ((eq (first form) 'RETURN-FROM)
1183         (single-valued-p (third form)))
1184        ((eq (first form) 'THE)
1185         (dformat t "single-valued-p THE ~S~%" form)
1186         (single-valued-p (third form)))
1187        ((eq (first form) (compiland-name *current-compiland*))
1188         (dformat t "single-valued-p recursive call ~S~%" (first form))
1189         (compiland-single-valued-p *current-compiland*))
1190        (t
1191         (sys:single-valued-p (car form)))))
1192
1193(defun emit-clear-values ()
1194;;   (break "EMIT-CLEAR-VALUES called~%")
1195  (ensure-thread-var-initialized)
1196  (emit 'clear-values))
1197
1198(defun maybe-emit-clear-values (form)
1199  (declare (optimize speed))
1200  (unless (single-valued-p form)
1201;;     (format t "Not single-valued: ~S~%" form)
1202    (ensure-thread-var-initialized)
1203    (emit 'clear-values)))
1204
1205(defun emit-unbox-fixnum ()
1206  (declare (optimize speed))
1207  (cond ((= *safety* 3)
1208         (emit-invokestatic +lisp-fixnum-class+ "getValue"
1209                            (list +lisp-object+) "I"))
1210        (t
1211         (emit 'checkcast +lisp-fixnum-class+)
1212         (emit 'getfield +lisp-fixnum-class+ "value" "I"))))
1213
1214(defun emit-box-long ()
1215  (declare (optimize speed))
1216  (emit-invokestatic +lisp-class+ "number" (list "J") +lisp-object+))
1217
1218;; Expects value on stack.
1219(defun emit-invoke-method (method-name target representation)
1220  (emit-invokevirtual +lisp-object-class+ method-name nil +lisp-object+)
1221  (when (eq representation :unboxed-fixnum)
1222    (emit-unbox-fixnum))
1223  (emit-move-from-stack target representation))
1224
1225(defvar *style-warnings* nil)
1226(defvar *warnings* nil)
1227(defvar *errors* nil)
1228
1229(defun compiler-style-warn (format-control &rest format-arguments)
1230  (incf *style-warnings*)
1231  (warn 'style-warning
1232        :format-control format-control
1233        :format-arguments format-arguments))
1234
1235(defun compiler-warn (format-control &rest format-arguments)
1236  (incf *warnings*)
1237  (warn 'warning
1238        :format-control format-control
1239        :format-arguments format-arguments))
1240
1241(defun compiler-error (format-control &rest format-arguments)
1242  (incf *errors*)
1243  (error 'compiler-error
1244         :format-control format-control
1245         :format-arguments format-arguments))
1246
1247(defun compiler-unsupported (format-control &rest format-arguments)
1248  (error 'compiler-unsupported-feature-error
1249         :format-control format-control
1250         :format-arguments format-arguments))
1251
1252;; "In addition to situations for which the standard specifies
1253;; that conditions of type WARNING must or might be signaled, warnings might be
1254;; signaled in situations where the compiler can determine that the
1255;; consequences are undefined or that a run-time error will be signaled.
1256;; Examples of this situation are as follows: violating type declarations,
1257;; altering or assigning the value of a constant defined with DEFCONSTANT,
1258;; calling built-in Lisp functions with a wrong number of arguments or
1259;; malformed keyword argument lists, and using unrecognized declaration
1260;; specifiers." (3.2.5)
1261(defun check-arg-count (form n)
1262  (declare (type fixnum n))
1263  (let* ((op (car form))
1264         (args (cdr form))
1265         (ok (= (length args) n)))
1266    (unless ok
1267      (funcall (if (eq (symbol-package op) sys:+cl-package+)
1268                   #'compiler-warn ; See above!
1269                   #'compiler-style-warn)
1270               "Wrong number of arguments for ~A (expected ~D, but received ~D)."
1271               op n (length args)))
1272    ok))
1273
1274(defparameter *resolvers* (make-hash-table :test #'eql))
1275
1276(defun unsupported-opcode (instruction)
1277  (error "Unsupported opcode ~D." (instruction-opcode instruction)))
1278
1279(dotimes (n (1+ *last-opcode*))
1280  (setf (gethash n *resolvers*) #'unsupported-opcode))
1281
1282;; The following opcodes resolve to themselves.
1283(dolist (n '(0 ; NOP
1284             1 ; ACONST_NULL
1285             2 ; ICONST_M1
1286             3 ; ICONST_0
1287             4 ; ICONST_1
1288             5 ; ICONST_2
1289             6 ; ICONST_3
1290             7 ; ICONST_4
1291             8 ; ICONST_5
1292             9 ; LCONST_0
1293             10 ; LCONST_1
1294             42 ; ALOAD_0
1295             43 ; ALOAD_1
1296             44 ; ALOAD_2
1297             45 ; ALOAD_3
1298             50 ; AALOAD
1299             75 ; ASTORE_0
1300             76 ; ASTORE_1
1301             77 ; ASTORE_2
1302             78 ; ASTORE_3
1303             83 ; AASTORE
1304             87 ; POP
1305             89 ; DUP
1306             90 ; DUP_X1
1307             91 ; DUP_X2
1308             95 ; SWAP
1309             96 ; IADD
1310             97 ; LADD
1311             100 ; ISUB
1312             101 ; LSUB
1313             116 ; INEG
1314             120 ; ISHL
1315             121 ; LSHL
1316             122 ; ISHR
1317             123 ; LSHR
1318             126 ; IAND
1319             132 ; IINC
1320             133 ; I2L
1321             136 ; L2I
1322             153 ; IFEQ
1323             154 ; IFNE
1324             155 ; IFGE
1325             156 ; IFGT
1326             157 ; IFGT
1327             158 ; IFLE
1328             159 ; IF_ICMPEQ
1329             160 ; IF_ICMPNE
1330             161 ; IF_ICMPLT
1331             162 ; IF_ICMPGE
1332             163 ; IF_ICMPGT
1333             164 ; IF_ICMPLE
1334             165 ; IF_ACMPEQ
1335             166 ; IF_ACMPNE
1336             167 ; GOTO
1337             168 ; JSR
1338             169 ; RET
1339             176 ; ARETURN
1340             177 ; RETURN
1341             190 ; ARRAYLENGTH
1342             191 ; ATHROW
1343             198 ; IFNULL
1344             202 ; LABEL
1345             ))
1346  (setf (gethash n *resolvers*) nil))
1347
1348(defmacro define-resolver (opcodes args &body body)
1349  (let ((name (gensym)))
1350    (if (listp opcodes)
1351        `(progn
1352           (defun ,name ,args ,@body)
1353           (eval-when (:load-toplevel :execute)
1354             (dolist (op ',opcodes)
1355               (setf (gethash op *resolvers*) (symbol-function ',name)))))
1356        `(progn
1357           (defun ,name ,args ,@body)
1358           (eval-when (:load-toplevel :execute)
1359             (setf (gethash ,opcodes *resolvers*) (symbol-function ',name)))))))
1360
1361;; ALOAD
1362(define-resolver 25 (instruction)
1363 (let* ((args (instruction-args instruction))
1364        (index (car args)))
1365   (cond ((<= 0 index 3)
1366          (inst (+ index 42)))
1367         ((<= 0 index 255)
1368          (inst 25 index))
1369         (t
1370          (error "ALOAD unsupported case")))))
1371
1372;; ILOAD
1373(define-resolver 21 (instruction)
1374  (let* ((args (instruction-args instruction))
1375         (index (car args)))
1376    (cond ((<= 0 index 3)
1377           (inst (+ index 26)))
1378          ((<= 0 index 255)
1379           (inst 21 index))
1380          (t
1381           (error "ILOAD unsupported case")))))
1382
1383;; ASTORE
1384(define-resolver 58 (instruction)
1385  (let* ((args (instruction-args instruction))
1386         (index (car args)))
1387    (cond ((<= 0 index 3)
1388           (inst (+ index 75)))
1389          ((<= 0 index 255)
1390           (inst 58 index))
1391          (t
1392           (error "ASTORE unsupported case")))))
1393
1394;; ISTORE
1395(define-resolver 54 (instruction)
1396  (let* ((args (instruction-args instruction))
1397         (index (car args)))
1398    (cond ((<= 0 index 3)
1399           (inst (+ index 59)))
1400          ((<= 0 index 255)
1401           (inst 54 index))
1402          (t
1403           (error "ASTORE unsupported case")))))
1404
1405;; GETSTATIC, PUTSTATIC
1406(define-resolver (178 179) (instruction)
1407  (let* ((args (instruction-args instruction))
1408         (index (pool-field (first args) (second args) (third args))))
1409    (inst (instruction-opcode instruction) (u2 index))))
1410
1411;; BIPUSH, SIPUSH
1412(define-resolver (16 17) (instruction)
1413  (let* ((args (instruction-args instruction))
1414         (n (first args)))
1415    (cond ((<= 0 n 5)
1416           (inst (+ n 3)))
1417          ((<= -128 n 127)
1418           (inst 16 (logand n #xff))) ; BIPUSH
1419          (t ; SIPUSH
1420           (inst 17 (u2 n))))))
1421
1422;; INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC class-name method-name descriptor
1423(define-resolver (182 183 184) (instruction)
1424  (let* ((args (instruction-args instruction))
1425         (index (pool-method (first args) (second args) (third args))))
1426    (setf (instruction-args instruction) (u2 index))
1427    instruction))
1428
1429;; LDC
1430(define-resolver 18 (instruction)
1431  (let* ((args (instruction-args instruction)))
1432    (unless (= (length args) 1)
1433      (error "Wrong number of args for LDC."))
1434    (if (> (car args) 255)
1435        (inst 19 (u2 (car args))) ; LDC_W
1436        (inst 18 args))))
1437
1438;; GETFIELD, PUTFIELD class-name field-name type-name
1439(define-resolver (180 181) (instruction)
1440  (let* ((args (instruction-args instruction))
1441         (index (pool-field (first args) (second args) (third args))))
1442    (inst (instruction-opcode instruction) (u2 index))))
1443
1444;; NEW, ANEWARRAY, CHECKCAST, INSTANCEOF class-name
1445(define-resolver (187 189 192 193) (instruction)
1446  (let* ((args (instruction-args instruction))
1447         (index (pool-class (first args))))
1448    (inst (instruction-opcode instruction) (u2 index))))
1449
1450(defun resolve-instruction (instruction)
1451  (declare (optimize speed))
1452  (let ((resolver (gethash (instruction-opcode instruction) *resolvers*)))
1453    (if resolver
1454        (funcall resolver instruction)
1455        instruction)))
1456
1457(defun resolve-instructions (code)
1458  (let ((vector (make-array 512 :fill-pointer 0 :adjustable t)))
1459    (dotimes (index (the fixnum (length code)) vector)
1460      (declare (type fixnum index))
1461      (let ((instruction (svref code index)))
1462        (case (instruction-opcode instruction)
1463          (205 ; CLEAR-VALUES
1464           (let ((instructions
1465                  (list
1466                   (inst 'aload *thread*)
1467                   (inst 'aconst_null)
1468                   (inst 'putfield (list +lisp-thread-class+ "_values"
1469                                         "[Lorg/armedbear/lisp/LispObject;")))))
1470             (dolist (instruction instructions)
1471               (vector-push-extend (resolve-instruction instruction) vector))))
1472          (t
1473           (vector-push-extend (resolve-instruction instruction) vector)))))))
1474
1475;; (defconstant +branch-opcodes+
1476;;   '(153 ; IFEQ
1477;;     154 ; IFNE
1478;;     155 ; IFLT
1479;;     156 ; IFGE
1480;;     157 ; IFGT
1481;;     158 ; IFLE
1482;;     159 ; IF_ICMPEQ
1483;;     160 ; IF_ICMPNE
1484;;     161 ; IF_ICMPLT
1485;;     162 ; IF_ICMPGE
1486;;     163 ; IF_ICMPGT
1487;;     164 ; IF_ICMPLE
1488;;     165 ; IF_ACMPEQ
1489;;     166 ; IF_ACMPNE
1490;;     167 ; GOTO
1491;;     168 ; JSR
1492;;     198 ; IFNULL
1493;;     ))
1494
1495(defun branch-opcode-p (opcode)
1496  (declare (optimize speed))
1497;;   (member opcode +branch-opcodes+)
1498  (or (<= 153 opcode 168)
1499      (= opcode 198)))
1500
1501(defun walk-code (code start-index depth)
1502  (declare (optimize speed))
1503  (do* ((i start-index (1+ i))
1504        (limit (length code)))
1505       ((>= i limit))
1506    (declare (type fixnum i limit))
1507    (let ((instruction (aref code i)))
1508      (when (instruction-depth instruction)
1509        (unless (eql (instruction-depth instruction) (+ depth (instruction-stack instruction)))
1510          (fresh-line)
1511          (%format t "Stack inconsistency at index ~D: found ~S, expected ~S.~%"
1512                   i
1513                   (instruction-depth instruction)
1514                   (+ depth (instruction-stack instruction))))
1515        (return-from walk-code))
1516      (let ((opcode (instruction-opcode instruction)))
1517        (unless (eql opcode 168) ; JSR
1518          (setf depth (+ depth (instruction-stack instruction))))
1519        (setf (instruction-depth instruction) depth)
1520        (if (eql opcode 168) ; JSR
1521            (let ((label (car (instruction-args instruction))))
1522              (walk-code code (symbol-value label) (1+ depth)))
1523            (when (branch-opcode-p opcode)
1524              (let ((label (car (instruction-args instruction))))
1525                (walk-code code (symbol-value label) depth))))
1526        (when (member opcode '(167 169 176 191)) ; GOTO RET ATHROW
1527          ;; Current path ends.
1528          (return-from walk-code))))))
1529
1530(defun analyze-stack ()
1531  (let* ((code *code*)
1532         (code-length (length code)))
1533    (declare (type fixnum code-length))
1534    (aver (vectorp code))
1535    (dotimes (i code-length)
1536      (declare (type fixnum i))
1537      (let* ((instruction (aref code i))
1538             (opcode (instruction-opcode instruction)))
1539        (when (eql opcode 202) ; LABEL
1540          (let ((label (car (instruction-args instruction))))
1541            (set label i)))
1542        (if (instruction-stack instruction)
1543            (when (opcode-stack-effect opcode)
1544              (unless (eql (instruction-stack instruction) (opcode-stack-effect opcode))
1545                (%format t "instruction-stack = ~S opcode-stack-effect = ~S~%"
1546                         (instruction-stack instruction)
1547                         (opcode-stack-effect opcode))
1548                (%format t "index = ~D instruction = ~A~%" i (print-instruction instruction))))
1549            (setf (instruction-stack instruction) (opcode-stack-effect opcode)))
1550;;         (aver (not (null (instruction-stack instruction))))
1551        (unless (instruction-stack instruction)
1552          (%format t "no stack information for instruction ~D~%" (instruction-opcode instruction))
1553          (aver nil))))
1554    (walk-code code 0 0)
1555    (dolist (handler *handlers*)
1556      ;; Stack depth is always 1 when handler is called.
1557      (walk-code code (symbol-value (handler-code handler)) 1))
1558    (let ((max-stack 0))
1559      (dotimes (i code-length)
1560        (declare (type fixnum i))
1561        (let* ((instruction (aref code i))
1562               (depth (instruction-depth instruction)))
1563          (when depth
1564            (setf max-stack (max max-stack depth)))))
1565      (when *compiler-debug*
1566        (%format t "compiland name = ~S~%" (compiland-name *current-compiland*))
1567        (%format t "max-stack = ~D~%" max-stack)
1568        (%format t "----- after stack analysis -----~%")
1569        (print-code))
1570      max-stack)))
1571
1572(defun emit-move-from-stack (target &optional representation)
1573  (declare (optimize speed))
1574  (cond ((null target)
1575         (emit 'pop))
1576        ((eq target :stack))
1577        ((fixnump target)
1578         (emit (if (eq representation :unboxed-fixnum) 'istore 'astore) target))
1579        (t
1580         (aver nil))))
1581
1582(defun resolve-variables ()
1583  (let ((code (nreverse *code*)))
1584    (setf *code* nil)
1585    (dolist (instruction code)
1586      (case (instruction-opcode instruction)
1587        (206 ; VAR-REF
1588         (let* ((instruction-args (instruction-args instruction))
1589                (variable (first instruction-args))
1590                (target (second instruction-args))
1591                (representation (third instruction-args)))
1592           (aver (variable-p variable))
1593           (dformat t "var-ref variable = ~S " (variable-name variable))
1594           (cond ((variable-register variable)
1595                  (dformat t "register = ~S~%" (variable-register variable))
1596                  (emit 'aload (variable-register variable))
1597                  (emit-move-from-stack target))
1598                 ((variable-special-p variable)
1599                  (dformat t "special~%")
1600                  (compile-special-reference (variable-name variable) target nil))
1601                 ((variable-closure-index variable)
1602                  (dformat t "closure-index = ~S~%" (variable-closure-index variable))
1603                  (aver (not (null (compiland-closure-register *current-compiland*))))
1604                  (emit 'aload (compiland-closure-register *current-compiland*))
1605                  (emit-push-constant-int (variable-closure-index variable))
1606                  (emit 'aaload)
1607                  (emit-move-from-stack target))
1608                 ((variable-index variable)
1609                  (dformat t "index = ~S~%" (variable-index variable))
1610                  (aver (not (null (compiland-argument-register *current-compiland*))))
1611                  (emit 'aload (compiland-argument-register *current-compiland*))
1612                  (emit-push-constant-int (variable-index variable))
1613                  (emit 'aaload)
1614                  (emit-move-from-stack target))
1615                 (t
1616                  (dformat t "VAR-REF unhandled case variable = ~S~%" (variable-name variable))
1617                  (aver (progn 'unhandled-case nil))))
1618           (when (eq representation :unboxed-fixnum)
1619             (dformat t "resolve-variables calling emit-unbox-fixnum~%")
1620             (emit-unbox-fixnum))))
1621        (207 ; VAR-SET
1622         (let ((variable (car (instruction-args instruction))))
1623           (dformat t "var-set variable = ~S " (variable-name variable))
1624           (aver (variable-p variable))
1625           (aver (not (variable-special-p variable)))
1626           (cond ((variable-register variable)
1627                  (dformat t "register = ~S~%" (variable-register variable))
1628                  (emit 'astore (variable-register variable)))
1629                 ((variable-closure-index variable)
1630                  (dformat t "closure-index = ~S~%" (variable-closure-index variable))
1631                  (aver (not (null (compiland-closure-register *current-compiland*))))
1632                  (emit 'aload (compiland-closure-register *current-compiland*))
1633                  (emit 'swap) ; array value
1634                  (emit 'bipush (variable-closure-index variable))
1635                  (emit 'swap) ; array index value
1636                  (emit 'aastore))
1637                 (t
1638                  (dformat t "var-set fall-through case~%")
1639                  (aver (not (null (compiland-argument-register *current-compiland*))))
1640                  (emit 'aload (compiland-argument-register *current-compiland*)) ; Stack: value array
1641                  (emit 'swap) ; array value
1642                  (emit 'bipush (variable-index variable)) ; array value index
1643                  (emit 'swap) ; array index value
1644                  (emit 'aastore)))))
1645        (t
1646         (push instruction *code*))))))
1647
1648(defun finalize-code ()
1649  (setf *code* (nreverse (coerce *code* 'vector))))
1650
1651(defun print-code ()
1652  (dotimes (i (length *code*))
1653    (let ((instruction (elt *code* i)))
1654      (%format t "~D ~A ~S ~S ~S~%"
1655               i
1656               (opcode-name (instruction-opcode instruction))
1657               (instruction-args instruction)
1658               (instruction-stack instruction)
1659               (instruction-depth instruction)))))
1660
1661(defun print-code2 (code)
1662  (dotimes (i (length code))
1663    (let ((instruction (elt code i)))
1664      (case (instruction-opcode instruction)
1665        (202 ; LABEL
1666         (format t "~A:~%" (car (instruction-args instruction))))
1667        (t
1668         (format t "~8D:   ~A ~S~%"
1669                 i
1670                 (opcode-name (instruction-opcode instruction))
1671                 (instruction-args instruction)))))))
1672
1673(defun label-p (instruction)
1674;;   (declare (optimize safety))
1675;;   (declare (type instruction instruction))
1676  (and instruction
1677       (= (the fixnum (instruction-opcode (the instruction instruction))) 202)))
1678
1679(defun instruction-label (instruction)
1680  (declare (optimize safety))
1681;;   (declare (type instruction instruction))
1682  (and instruction
1683       (= (instruction-opcode (the instruction instruction)) 202)
1684       (car (instruction-args instruction))))
1685
1686;; Remove unused labels.
1687(defun optimize-1 ()
1688  (let ((code (coerce *code* 'list))
1689        (changed nil)
1690        (marker (gensym)))
1691    ;; Mark the labels that are actually branched to.
1692    (dolist (instruction code)
1693      (when (branch-opcode-p (instruction-opcode instruction))
1694        (let ((label (car (instruction-args instruction))))
1695          (set label marker))))
1696    ;; Add labels used for exception handlers.
1697    (dolist (handler *handlers*)
1698      (set (handler-from handler) marker)
1699      (set (handler-to handler) marker)
1700      (set (handler-code handler) marker))
1701    ;; Remove labels that are not used as branch targets.
1702    (let ((tail code))
1703      (loop
1704        (when (null tail)
1705          (return))
1706        (let ((instruction (car tail)))
1707          (when (= (instruction-opcode instruction) 202) ; LABEL
1708            (let ((label (car (instruction-args instruction))))
1709              (unless (eq (symbol-value label) marker)
1710                (setf (car tail) nil)
1711                (setf changed t)))))
1712        (setf tail (cdr tail))))
1713    (when changed
1714      (setf *code* (delete nil code))
1715      t)))
1716
1717(defun optimize-2 ()
1718  (let* ((code (coerce *code* 'list))
1719         (tail code)
1720         (changed nil))
1721    (loop
1722      (when (null (cdr tail))
1723        (return))
1724      (let ((instruction (car tail))
1725            next-instruction)
1726        (when (and instruction
1727                   (= (instruction-opcode instruction) 167) ; GOTO
1728                   (setf next-instruction (cadr tail)))
1729          (cond ((and (= (instruction-opcode next-instruction) 202) ; LABEL
1730                      (eq (car (instruction-args instruction))
1731                          (car (instruction-args next-instruction))))
1732                 ;; GOTO next instruction: we don't need this one.
1733                 (setf (car tail) nil)
1734                 (setf changed t))
1735                ((= (instruction-opcode next-instruction) 167) ; GOTO
1736                 ;; Two GOTOs in a row: the next instruction is unreachable.
1737                 (setf (cadr tail) nil)
1738                 (setf changed t)))))
1739      (setf tail (cdr tail)))
1740    (when changed
1741      (setf *code* (delete nil code))
1742      t)))
1743
1744(defun hash-labels (code)
1745  (let ((ht (make-hash-table :test 'eq))
1746        (code (coerce code 'list))
1747        (pending-label nil))
1748    (dolist (instruction code)
1749      (when pending-label
1750        (setf (gethash pending-label ht) instruction)
1751        (setf pending-label nil))
1752      (when (label-p instruction)
1753        (setf pending-label (instruction-label instruction))))
1754    ht))
1755
1756(defun optimize-2b ()
1757  (let* ((code (coerce *code* 'list))
1758         (ht (hash-labels code))
1759         (changed nil))
1760    (dolist (instruction code)
1761      (when (and instruction (= (instruction-opcode instruction) 167)) ; GOTO
1762        (let* ((target-label (car (instruction-args instruction)))
1763               (next-instruction (gethash target-label ht)))
1764          (when next-instruction
1765            (case (instruction-opcode next-instruction)
1766              (167 ; GOTO
1767               (setf (instruction-args instruction)
1768                     (instruction-args next-instruction)
1769                     changed t))
1770              (176 ; ARETURN
1771               (setf (instruction-opcode instruction) 176
1772                     (instruction-args instruction) nil
1773                     changed t))
1774              )))))
1775    (when changed
1776      (setf *code* (delete nil code))
1777      t)))
1778
1779;; CLEAR-VALUES CLEAR-VALUES => CLEAR-VALUES
1780;; GETSTATIC POP => nothing
1781(defun optimize-3 ()
1782  (let* ((code (coerce *code* 'list))
1783         (tail code)
1784         (changed nil))
1785    (loop
1786      (when (null (cdr tail))
1787        (return))
1788      (let ((this-opcode (instruction-opcode (car tail)))
1789            (next-opcode (instruction-opcode (cadr tail))))
1790        (case this-opcode
1791          (205 ; CLEAR-VALUES
1792           (when (eql next-opcode 205) ; CLEAR-VALUES
1793             (setf (car tail) (cadr tail)
1794                   (cdr tail) (cddr tail)
1795                   changed t)))
1796          (178 ; GETSTATIC
1797           (when (eql next-opcode 87) ; POP
1798             (setf (car tail) (caddr tail)
1799                   (cdr tail) (cdddr tail)
1800                   changed t)))))
1801      (setf tail (cdr tail)))
1802    (when changed
1803      (setf *code* code)
1804      t)))
1805
1806(defvar *delete-unreachable-code-flag* t)
1807
1808(defun delete-unreachable-code ()
1809  (when *delete-unreachable-code-flag*
1810      ;; Look for unreachable code after GOTO.
1811      (unless (listp *code*)
1812        (setf *code* (coerce *code* 'list)))
1813      (let* ((code *code*)
1814             (tail code)
1815             (locally-changed-p nil)
1816             (after-goto nil))
1817        (loop
1818          (when (null tail)
1819            (return))
1820          (let ((instruction (car tail)))
1821            (cond (after-goto
1822                   (if (= (instruction-opcode instruction) 202) ; LABEL
1823                       (setf after-goto nil)
1824                       ;; Unreachable.
1825                       (progn
1826                         (setf (car tail) nil)
1827                         (setf locally-changed-p t))))
1828                  ((= (instruction-opcode instruction) 167) ; GOTO
1829                   (setf after-goto t))))
1830          (setf tail (cdr tail)))
1831        (when locally-changed-p
1832          (setf *code* (delete nil code))
1833          t))))
1834
1835(defvar *enable-optimization* t)
1836
1837(defun optimize-code ()
1838  (unless *enable-optimization*
1839    (%format t "optimizations are disabled~%"))
1840  (when *enable-optimization*
1841    (when *compiler-debug*
1842      (%format t "----- before optimization -----~%")
1843      (print-code))
1844    (loop
1845      (let ((changed-p nil))
1846        (setf changed-p (or (optimize-1) changed-p))
1847        (setf changed-p (or (optimize-2) changed-p))
1848        (setf changed-p (or (optimize-2b) changed-p))
1849        (setf changed-p (or (optimize-3) changed-p))
1850        (setf changed-p (or (delete-unreachable-code) changed-p))
1851        (unless changed-p
1852          (return))))
1853    (unless (typep *code* 'vector)
1854      (setf *code* (coerce *code* 'vector)))
1855    (when *compiler-debug*
1856      (%format t "----- after optimization -----~%")
1857      (print-code))))
1858
1859(defun code-bytes (code)
1860  (let ((length 0))
1861    (declare (type fixnum length))
1862    ;; Pass 1: calculate label offsets and overall length.
1863    (dotimes (i (the fixnum (length code)))
1864      (declare (type fixnum i))
1865      (let* ((instruction (aref code i))
1866             (opcode (instruction-opcode instruction)))
1867        (if (= opcode 202) ; LABEL
1868            (let ((label (car (instruction-args instruction))))
1869              (set label length))
1870            (incf length (opcode-size opcode)))))
1871    ;; Pass 2: replace labels with calculated offsets.
1872    (let ((index 0))
1873;;       (declare (type fixnum index))
1874      (dotimes (i (length code))
1875        (declare (type fixnum i))
1876        (let ((instruction (aref code i)))
1877          (when (branch-opcode-p (instruction-opcode instruction))
1878            (let* ((label (car (instruction-args instruction)))
1879                   (offset (- (symbol-value `,label) index)))
1880              (setf (instruction-args instruction) (u2 offset))))
1881          (unless (= (instruction-opcode instruction) 202) ; LABEL
1882            (incf index (opcode-size (instruction-opcode instruction)))))))
1883    ;; Expand instructions into bytes, skipping LABEL pseudo-instructions.
1884    (let ((bytes (make-array length))
1885          (index 0))
1886;;       (declare (type fixnum index))
1887      (dotimes (i (length code))
1888        (declare (type fixnum i))
1889        (let ((instruction (aref code i)))
1890          (unless (= (instruction-opcode instruction) 202) ; LABEL
1891            (setf (svref bytes index) (instruction-opcode instruction))
1892            (incf index)
1893            (dolist (byte (instruction-args instruction))
1894              (setf (svref bytes index) byte)
1895              (incf index)))))
1896      bytes)))
1897
1898(defsubst write-u1 (n stream)
1899  (declare (optimize speed))
1900  (sys::write-8-bits n stream))
1901
1902(defun write-u2 (n stream)
1903  (declare (optimize speed))
1904  (sys::write-8-bits (ash n -8) stream)
1905  (sys::write-8-bits (logand n #xFF) stream))
1906
1907(defun write-u4 (n stream)
1908  (declare (optimize speed))
1909  (write-u2 (ash n -16) stream)
1910  (write-u2 (logand n #xFFFF) stream))
1911
1912(defun write-s4 (n stream)
1913  (declare (optimize speed))
1914  (cond ((minusp n)
1915         (write-u4 (1+ (logxor (- n) #xFFFFFFFF)) stream))
1916        (t
1917         (write-u4 n stream))))
1918
1919(defun write-utf8 (string stream)
1920  (declare (optimize speed))
1921  (dotimes (i (length string))
1922    (declare (type fixnum i))
1923    (let ((c (schar string i)))
1924      (if (eql c #\null)
1925          (progn
1926            (sys::write-8-bits #xC0 stream)
1927            (sys::write-8-bits #x80 stream))
1928          (sys::write-8-bits (char-int c) stream)))))
1929
1930(defun utf8-length (string)
1931  (declare (optimize speed))
1932  (let ((length (length string)))
1933    (declare (type fixnum length))
1934    (dotimes (i length)
1935      (declare (type fixnum i))
1936      (when (eql (schar string i) #\null)
1937        (incf length)))
1938    length))
1939
1940(defun write-constant-pool-entry (entry stream)
1941  (declare (optimize speed))
1942  (let ((tag (first entry)))
1943    (write-u1 tag stream)
1944    (case tag
1945      (1 ; UTF8
1946       (write-u2 (utf8-length (third entry)) stream)
1947       (write-utf8 (third entry) stream))
1948      (3 ; int
1949       (write-s4 (second entry) stream))
1950      ((5 6)
1951       (write-u4 (second entry) stream)
1952       (write-u4 (third entry)) stream)
1953      ((9 10 11 12)
1954       (write-u2 (second entry) stream)
1955       (write-u2 (third entry) stream))
1956      ((7 8)
1957       (write-u2 (second entry) stream))
1958      (t
1959       (error "write-constant-pool-entry unhandled tag ~D~%" tag)))))
1960
1961(defun write-constant-pool (stream)
1962  (declare (optimize speed))
1963  (write-u2 *pool-count* stream)
1964  (dolist (entry (reverse *pool*))
1965    (write-constant-pool-entry entry stream)))
1966
1967(defstruct field
1968  access-flags
1969  name
1970  descriptor
1971  name-index
1972  descriptor-index)
1973
1974(defstruct (java-method (:conc-name method-) (:constructor make-method))
1975  access-flags
1976  name
1977  descriptor
1978  name-index
1979  descriptor-index
1980  max-stack
1981  max-locals
1982  code
1983  handlers)
1984
1985(defun make-constructor (super args)
1986;;   (%format t "make-constructor (length *static-code*) = ~S~%" (length *static-code*))
1987  (let* ((*compiler-debug* nil) ; We don't normally need to see debugging output for constructors.
1988         (constructor (make-method :name "<init>"
1989                                   :descriptor "()V"))
1990         (*code* ())
1991         (*handlers* nil))
1992    (dformat t "make-constructor super = ~S~%" super)
1993    (setf (method-name-index constructor) (pool-name (method-name constructor)))
1994    (setf (method-descriptor-index constructor) (pool-name (method-descriptor constructor)))
1995    (setf (method-max-locals constructor) 1)
1996    (cond ((equal super +lisp-compiled-function-class+)
1997           (emit 'aload_0) ;; this
1998           (emit 'aconst_null) ;; name
1999           (let* ((*print-level* nil)
2000                  (*print-length* nil)
2001                  (s (%format nil "~S" args)))
2002             (emit 'ldc (pool-string s))
2003             (emit-invokestatic +lisp-class+ "readObjectFromString"
2004                                (list +java-string+) +lisp-object+))
2005           (emit-push-nil) ;; body
2006           (emit 'aconst_null) ;; environment
2007           (emit-invokespecial-init super
2008                                    (list +lisp-symbol+ +lisp-object+
2009                                          +lisp-object+ +lisp-environment+)))
2010          ((equal super +lisp-primitive-class+)
2011           (emit 'aload_0)
2012           (emit-invokespecial-init super nil))
2013          ((equal super +lisp-ctf-class+)
2014           (emit 'aload_0) ;; this
2015           (let* ((*print-level* nil)
2016                  (*print-length* nil)
2017                  (s (%format nil "~S" args)))
2018             (emit 'ldc (pool-string s))
2019             (emit-invokestatic +lisp-class+ "readObjectFromString"
2020                                (list +java-string+) +lisp-object+))
2021           (emit-invokespecial-init super (list +lisp-object+)))
2022          (t
2023           (aver nil)))
2024    (setf *code* (append *static-code* *code*))
2025    (emit 'return)
2026    (finalize-code)
2027    ;;(optimize-code)
2028    (setf *code* (resolve-instructions *code*))
2029    (setf (method-max-stack constructor) (analyze-stack))
2030    (setf (method-code constructor) (code-bytes *code*))
2031    (setf (method-handlers constructor) (nreverse *handlers*))
2032    constructor))
2033
2034(defun write-exception-table (method stream)
2035  (let ((handlers (method-handlers method)))
2036    (write-u2 (length handlers) stream) ; number of entries
2037    (dolist (handler handlers)
2038      (write-u2 (symbol-value (handler-from handler)) stream)
2039      (write-u2 (symbol-value (handler-to handler)) stream)
2040      (write-u2 (symbol-value (handler-code handler)) stream)
2041      (write-u2 (handler-catch-type handler) stream))))
2042
2043(defun write-code-attr (method stream)
2044  (declare (optimize speed))
2045  (let* ((name-index (pool-name "Code"))
2046         (code (method-code method))
2047         (code-length (length code))
2048         (length (+ code-length 12
2049                    (* (length (method-handlers method)) 8)))
2050         (max-stack (or (method-max-stack method) 20))
2051         (max-locals (or (method-max-locals method) 1)))
2052    (write-u2 name-index stream)
2053    (write-u4 length stream)
2054    (write-u2 max-stack stream)
2055    (write-u2 max-locals stream)
2056    (write-u4 code-length stream)
2057    (dotimes (i code-length)
2058      (declare (type fixnum i))
2059      (write-u1 (svref code i) stream))
2060    (write-exception-table method stream)
2061    (write-u2 0 stream) ; attributes count
2062    ))
2063
2064(defun write-method (method stream)
2065  (declare (optimize speed))
2066  (write-u2 (or (method-access-flags method) #x1) stream) ; access flags
2067  (write-u2 (method-name-index method) stream)
2068  (write-u2 (method-descriptor-index method) stream)
2069  (write-u2 1 stream) ; attributes count
2070  (write-code-attr method stream))
2071
2072(defun write-field (field stream)
2073  (declare (optimize speed))
2074  (write-u2 (or (field-access-flags field) #x1) stream) ; access flags
2075  (write-u2 (field-name-index field) stream)
2076  (write-u2 (field-descriptor-index field) stream)
2077  (write-u2 0 stream)) ; attributes count
2078
2079(defun declare-field (name descriptor)
2080  (let ((field (make-field :name name :descriptor descriptor)))
2081    (setf (field-access-flags field) (logior #x8 #x2)) ; private static
2082    (setf (field-name-index field) (pool-name (field-name field)))
2083    (setf (field-descriptor-index field) (pool-name (field-descriptor field)))
2084    (push field *fields*)))
2085
2086(defun sanitize (symbol)
2087  (declare (optimize speed))
2088  (let* ((input (symbol-name symbol))
2089         (output (make-array (length input) :fill-pointer 0 :element-type 'character)))
2090    (dotimes (i (length input))
2091      (declare (type fixnum i))
2092      (let ((c (char-upcase (char input i))))
2093        (cond ((<= #.(char-code #\A) (char-code c) #.(char-code #\Z))
2094               (vector-push c output))
2095              ((eql c #\-)
2096               (vector-push #\_ output)))))
2097    (when (plusp (length output))
2098      output)))
2099
2100(defun declare-symbol (symbol)
2101  (let ((g (gethash symbol *declared-symbols*)))
2102    (unless g
2103      (let ((*code* *static-code*)
2104            (s (sanitize symbol)))
2105        (setf g (symbol-name (gensym)))
2106        (when s
2107          (setf g (concatenate 'string g "_" s)))
2108        (declare-field g +lisp-symbol+)
2109        (emit 'ldc (pool-string (symbol-name symbol)))
2110        (emit 'ldc (pool-string (package-name (symbol-package symbol))))
2111        (emit-invokestatic +lisp-class+ "internInPackage"
2112                           (list +java-string+ +java-string+) +lisp-symbol+)
2113        (emit 'putstatic *this-class* g +lisp-symbol+)
2114        (setf *static-code* *code*)
2115;;         (%format t "declare-symbol (length *static-code* = ~S~%" (length *static-code*))
2116        (setf (gethash symbol *declared-symbols*) g)))
2117    g))
2118
2119(defun declare-keyword (symbol)
2120  (let ((g (gethash symbol *declared-symbols*)))
2121    (unless g
2122      (let ((*code* *static-code*))
2123        (setf g (symbol-name (gensym)))
2124        (declare-field g +lisp-symbol+)
2125        (emit 'ldc (pool-string (symbol-name symbol)))
2126        (emit-invokestatic "org/armedbear/lisp/Keyword" "internKeyword"
2127                           (list +java-string+) +lisp-symbol+)
2128        (emit 'putstatic *this-class* g +lisp-symbol+)
2129        (setf *static-code* *code*)
2130        (setf (gethash symbol *declared-symbols*) g)))
2131    g))
2132
2133(defun declare-function (symbol)
2134  (let ((f (gethash symbol *declared-functions*)))
2135    (unless f
2136      (setf f (symbol-name (gensym)))
2137      (let ((s (sanitize symbol)))
2138        (when s
2139          (setf f (concatenate 'string f "_" s))))
2140      (let ((*code* *static-code*)
2141            (g (gethash symbol *declared-symbols*)))
2142        (cond (g
2143               (emit 'getstatic *this-class* g +lisp-symbol+))
2144              (t
2145               (emit 'ldc (pool-string (symbol-name symbol)))
2146               (emit 'ldc (pool-string (package-name (symbol-package symbol))))
2147               (emit-invokestatic +lisp-class+ "internInPackage"
2148                                  (list +java-string+ +java-string+)
2149                                  +lisp-symbol+)))
2150        (declare-field f +lisp-object+)
2151        (emit-invokevirtual +lisp-symbol-class+ "getSymbolFunctionOrDie"
2152                            nil +lisp-object+)
2153        (emit 'putstatic *this-class* f +lisp-object+)
2154        (setq *static-code* *code*)
2155        (setf (gethash symbol *declared-functions*) f)))
2156    f))
2157
2158(defun declare-setf-function (name)
2159  (let ((f (gethash name *declared-functions*)))
2160    (unless f
2161      (let ((symbol (cadr name)))
2162        (setf f (symbol-name (gensym)))
2163        (let ((s (sanitize symbol)))
2164          (when s
2165            (setf f (concatenate 'string f "_SETF_" s))))
2166        (let ((*code* *static-code*)
2167              (g (gethash symbol *declared-symbols*)))
2168          (cond (g
2169                 (emit 'getstatic *this-class* g +lisp-symbol+))
2170                (t
2171                 (emit 'ldc (pool-string (symbol-name symbol)))
2172                 (emit 'ldc (pool-string (package-name (symbol-package symbol))))
2173                 (emit-invokestatic +lisp-class+ "internInPackage"
2174                                    (list +java-string+ +java-string+)
2175                                    +lisp-symbol+)))
2176          (declare-field f +lisp-object+)
2177          (emit-invokevirtual +lisp-symbol-class+ "getSymbolSetfFunctionOrDie"
2178                              nil +lisp-object+)
2179          (emit 'putstatic *this-class* f +lisp-object+)
2180          (setq *static-code* *code*)
2181          (setf (gethash name *declared-functions*) f))))
2182    f))
2183
2184(defun declare-fixnum (n)
2185  (declare (type fixnum n))
2186  (let ((g (gethash n *declared-fixnums*)))
2187    (unless g
2188      (let ((*code* *static-code*))
2189        (setf g (%format nil "FIXNUM_~A~D"
2190                         (if (minusp n) "MINUS_" "")
2191                         (abs n)))
2192        (declare-field g +lisp-fixnum+)
2193        (emit 'new +lisp-fixnum-class+)
2194        (emit 'dup)
2195        (case n
2196          (-1
2197           (emit 'iconst_m1))
2198          (0
2199           (emit 'iconst_0))
2200          (1
2201           (emit 'iconst_1))
2202          (2
2203           (emit 'iconst_2))
2204          (3
2205           (emit 'iconst_3))
2206          (4
2207           (emit 'iconst_4))
2208          (5
2209           (emit 'iconst_5))
2210          (t
2211           (emit 'ldc (pool-int n))))
2212        (emit-invokespecial-init +lisp-fixnum-class+ '("I"))
2213        (emit 'putstatic *this-class* g +lisp-fixnum+)
2214        (setf *static-code* *code*)
2215        (setf (gethash n *declared-fixnums*) g)))
2216    g))
2217
2218(defun declare-object-as-string (obj)
2219  (let* ((g (symbol-name (gensym)))
2220         (*print-level* nil)
2221         (*print-length* nil)
2222         (s (%format nil "~S" obj))
2223         (*code* *static-code*))
2224    (declare-field g +lisp-object+)
2225    (emit 'ldc (pool-string s))
2226    (emit-invokestatic +lisp-class+ "readObjectFromString"
2227                       (list +java-string+) +lisp-object+)
2228    (emit 'putstatic *this-class* g +lisp-object+)
2229    (setf *static-code* *code*)
2230    g))
2231
2232(defun declare-load-time-value (obj)
2233  (let* ((g (symbol-name (gensym)))
2234         (*print-level* nil)
2235         (*print-length* nil)
2236         (s (%format nil "~S" obj))
2237         (*code* *static-code*))
2238    (declare-field g +lisp-object+)
2239    (emit 'ldc (pool-string s))
2240    (emit-invokestatic +lisp-class+ "readObjectFromString"
2241                       (list +java-string+) +lisp-object+)
2242    (emit-invokestatic +lisp-class+ "loadTimeValue"
2243                       (list +lisp-object+) +lisp-object+)
2244    (emit 'putstatic *this-class* g +lisp-object+)
2245    (setf *static-code* *code*)
2246    g))
2247
2248(defun declare-package (obj)
2249  (let* ((g (symbol-name (gensym)))
2250         (*print-level* nil)
2251         (*print-length* nil)
2252         (s (%format nil "#.(FIND-PACKAGE ~S)" (package-name obj)))
2253         (*code* *static-code*))
2254    (declare-field g +lisp-object+)
2255    (emit 'ldc (pool-string s))
2256    (emit-invokestatic +lisp-class+ "readObjectFromString"
2257                       (list +java-string+) +lisp-object+)
2258    (emit 'putstatic *this-class* g +lisp-object+)
2259    (setf *static-code* *code*)
2260    g))
2261
2262(defun declare-object (obj)
2263  (let ((key (symbol-name (gensym))))
2264    (sys::remember key obj)
2265    (let* ((g1 (declare-string key))
2266           (g2 (symbol-name (gensym)))
2267           (*code* *static-code*))
2268      (declare-field g2 +lisp-object+)
2269      (emit 'getstatic *this-class* g1 +lisp-string+)
2270      (emit-invokestatic +lisp-class+ "recall"
2271                         (list +lisp-simple-string+) +lisp-object+)
2272      (emit 'putstatic *this-class* g2 +lisp-object+)
2273      (setf *static-code* *code*)
2274      g2)))
2275
2276(defun declare-lambda (obj)
2277  (let* ((g (symbol-name (gensym)))
2278         (*print-level* nil)
2279         (*print-length* nil)
2280         (s (%format nil "~S" obj))
2281         (*code* *static-code*))
2282    (declare-field g +lisp-object+)
2283    (emit 'ldc
2284          (pool-string s))
2285    (emit-invokestatic +lisp-class+ "readObjectFromString"
2286                       (list +java-string+) +lisp-object+)
2287    (emit-invokestatic +lisp-class+ "coerceToFunction"
2288                       (list +lisp-object+) +lisp-object+)
2289    (emit 'putstatic *this-class* g +lisp-object+)
2290    (setf *static-code* *code*)
2291    g))
2292
2293(defun declare-local-function (local-function)
2294  (let* ((g (symbol-name (gensym)))
2295         (pathname (class-file-pathname (local-function-class-file local-function)))
2296         (*code* *static-code*))
2297    (declare-field g +lisp-object+)
2298    (emit 'ldc (pool-string (file-namestring pathname)))
2299    (emit-invokestatic +lisp-class+ "loadCompiledFunction"
2300                       (list +java-string+) +lisp-object+)
2301    (emit 'putstatic *this-class* g +lisp-object+)
2302    (setf *static-code* *code*)
2303    g))
2304
2305(defun declare-string (string)
2306  (let ((g (gethash string *declared-strings*)))
2307    (unless g
2308      (let ((*code* *static-code*))
2309        (setf g (symbol-name (gensym)))
2310        (declare-field g +lisp-simple-string+)
2311        (emit 'new +lisp-simple-string-class+)
2312        (emit 'dup)
2313        (emit 'ldc (pool-string string))
2314        (emit-invokespecial-init +lisp-simple-string-class+ (list +java-string+))
2315        (emit 'putstatic *this-class* g +lisp-simple-string+)
2316        (setf *static-code* *code*)
2317        (setf (gethash string *declared-strings*) g)))
2318    g))
2319
2320(defun compile-constant (form &key (target :stack) representation)
2321  (unless target
2322    (return-from compile-constant))
2323  (when (eq representation :unboxed-fixnum)
2324    (cond ((fixnump form)
2325           (emit-push-constant-int form)
2326           (emit-move-from-stack target)
2327           (return-from compile-constant))
2328          (t
2329           (assert nil))))
2330  (cond ((numberp form)
2331         (if (fixnump form)
2332             (let* ((n form)
2333                    (translations '(( 0 . "ZERO")
2334                                    ( 1 . "ONE")
2335                                    ( 2 . "TWO")
2336                                    ( 3 . "THREE")
2337                                    (-1 . "MINUS_ONE")))
2338                    (translation (cdr (assoc n translations))))
2339               (if translation
2340                   (emit 'getstatic +lisp-fixnum-class+ translation +lisp-fixnum+)
2341                   (emit 'getstatic *this-class* (declare-fixnum n) +lisp-fixnum+)))
2342             (emit 'getstatic *this-class*
2343                   (declare-object-as-string form) +lisp-object+)))
2344        ((stringp form)
2345         (if *compile-file-truename*
2346             (emit 'getstatic *this-class*
2347                   (declare-string form) +lisp-simple-string+)
2348             (emit 'getstatic *this-class*
2349                   (declare-object form) +lisp-object+)))
2350        ((vectorp form)
2351         (if *compile-file-truename*
2352             (emit 'getstatic *this-class*
2353                   (declare-object-as-string form) +lisp-object+)
2354             (emit 'getstatic *this-class*
2355                   (declare-object form) +lisp-object+)))
2356        ((characterp form)
2357         (emit 'getstatic *this-class*
2358               (declare-object-as-string form) +lisp-object+))
2359        ((or (classp form) (hash-table-p form) (typep form 'generic-function))
2360         (emit 'getstatic *this-class*
2361               (declare-object form) +lisp-object+))
2362        ((pathnamep form)
2363         (let ((g (if *compile-file-truename*
2364                      (declare-object-as-string form)
2365                      (declare-object form))))
2366           (emit 'getstatic *this-class* g +lisp-object+)))
2367        ((packagep form)
2368         (let ((g (if *compile-file-truename*
2369                      (declare-package form)
2370                      (declare-object form))))
2371           (emit 'getstatic *this-class* g +lisp-object+)))
2372        (t
2373         (if *compile-file-truename*
2374             (error "COMPILE-CONSTANT unhandled case ~S" form)
2375             (emit 'getstatic *this-class*
2376                   (declare-object form) +lisp-object+))))
2377  (emit-move-from-stack target))
2378
2379(defparameter unary-operators (make-hash-table :test 'eq))
2380
2381(defun define-unary-operator (operator translation)
2382  (setf (gethash operator unary-operators) translation))
2383
2384;; (define-unary-operator '1+              "incr")
2385;; (define-unary-operator '1-              "decr")
2386(define-unary-operator 'ABS             "ABS")
2387(define-unary-operator 'ATOM            "ATOM")
2388(define-unary-operator 'BIT-VECTOR-P    "BIT_VECTOR_P")
2389(define-unary-operator 'CADR            "cadr")
2390(define-unary-operator 'CAR             "car")
2391(define-unary-operator 'CDDR            "cddr")
2392(define-unary-operator 'CDR             "cdr")
2393(define-unary-operator 'CHARACTERP      "CHARACTERP")
2394(define-unary-operator 'CLASS-OF        "classOf")
2395(define-unary-operator 'COMPLEXP        "COMPLEXP")
2396(define-unary-operator 'CONSTANTP       "CONSTANTP")
2397(define-unary-operator 'DENOMINATOR     "DENOMINATOR")
2398(define-unary-operator 'ENDP            "ENDP")
2399(define-unary-operator 'EVENP           "EVENP")
2400(define-unary-operator 'FIRST           "car")
2401(define-unary-operator 'FLOATP          "FLOATP")
2402(define-unary-operator 'INTEGERP        "INTEGERP")
2403(define-unary-operator 'LENGTH          "LENGTH")
2404(define-unary-operator 'LISTP           "LISTP")
2405(define-unary-operator 'MINUSP          "MINUSP")
2406(define-unary-operator 'NREVERSE        "nreverse")
2407(define-unary-operator 'NUMBERP         "NUMBERP")
2408(define-unary-operator 'NUMERATOR       "NUMERATOR")
2409(define-unary-operator 'ODDP            "ODDP")
2410(define-unary-operator 'PLUSP           "PLUSP")
2411(define-unary-operator 'RATIONALP       "RATIONALP")
2412(define-unary-operator 'REALP           "REALP")
2413(define-unary-operator 'REST            "cdr")
2414(define-unary-operator 'SECOND          "cadr")
2415(define-unary-operator 'SIMPLE-STRING-P "SIMPLE_STRING_P")
2416(define-unary-operator 'STRING          "STRING")
2417(define-unary-operator 'STRINGP         "STRINGP")
2418(define-unary-operator 'SYMBOLP         "SYMBOLP")
2419(define-unary-operator 'VECTORP         "VECTORP")
2420;; (define-unary-operator 'ZEROP           "ZEROP")
2421
2422(defun compile-function-call-1 (op args target representation)
2423  (let ((arg (first args)))
2424    (when (eq op '1+)
2425      (return-from compile-function-call-1 (p2-plus (list '+ arg 1)
2426                                                    :target target
2427                                                    :representation representation)))
2428    (when (eq op '1-)
2429      (return-from compile-function-call-1 (p2-minus (list '- arg 1)
2430                                                     :target target
2431                                                     :representation representation)))
2432    (let ((s (gethash op unary-operators)))
2433      (cond (s
2434             (compile-form arg :target :stack)
2435             (maybe-emit-clear-values arg)
2436             (emit-invoke-method s target representation)
2437             t)
2438            ((eq op 'LIST)
2439             (emit 'new +lisp-cons-class+)
2440             (emit 'dup)
2441             (compile-form arg :target :stack)
2442             (maybe-emit-clear-values arg)
2443             (emit-invokespecial-init +lisp-cons-class+ (list +lisp-object+))
2444             (emit-move-from-stack target)
2445             t)
2446            (t
2447             nil)))))
2448
2449(defparameter binary-operators (make-hash-table :test 'eq))
2450
2451(defun define-binary-operator (operator translation)
2452  (setf (gethash operator binary-operators) translation))
2453
2454(define-binary-operator 'eql                 "EQL")
2455(define-binary-operator 'equal               "EQUAL")
2456(define-binary-operator '+                   "add")
2457(define-binary-operator '-                   "subtract")
2458(define-binary-operator '/                   "divideBy")
2459(define-binary-operator '*                   "multiplyBy")
2460(define-binary-operator '<                   "IS_LT")
2461(define-binary-operator '<=                  "IS_LE")
2462(define-binary-operator '>                   "IS_GT")
2463(define-binary-operator '>=                  "IS_GE")
2464(define-binary-operator ' =                  "IS_E")
2465(define-binary-operator '/=                  "IS_NE")
2466(define-binary-operator 'ash                 "ash")
2467(define-binary-operator 'logand              "logand")
2468(define-binary-operator 'aref                "AREF")
2469(define-binary-operator 'sys::simple-typep   "typep")
2470(define-binary-operator 'rplaca              "RPLACA")
2471(define-binary-operator 'rplacd              "RPLACD")
2472(define-binary-operator 'sys::%rplaca        "_RPLACA")
2473(define-binary-operator 'sys::%rplacd        "_RPLACD")
2474
2475(defun compile-binary-operation (op args target representation)
2476  (compile-form (first args) :target :stack)
2477  (compile-form (second args) :target :stack)
2478  (unless (and (single-valued-p (first args))
2479               (single-valued-p (second args)))
2480    (emit-clear-values))
2481  (emit-invokevirtual +lisp-object-class+ op (list +lisp-object+) +lisp-object+)
2482  (when (eq representation :unboxed-fixnum)
2483    (emit-unbox-fixnum))
2484  (emit-move-from-stack target))
2485
2486(defun compile-function-call-2 (op args target representation)
2487  (let ((translation (gethash op binary-operators))
2488        (first (first args))
2489        (second (second args)))
2490    (if translation
2491        (compile-binary-operation translation args target representation)
2492        (case op
2493          (EQ
2494           (compile-form first :target :stack)
2495           (compile-form second :target :stack)
2496           (unless (and (single-valued-p first)
2497                        (single-valued-p second))
2498             (emit-clear-values))
2499           (let ((label1 (gensym))
2500                 (label2 (gensym)))
2501             (emit 'if_acmpeq `,label1)
2502             (emit-push-nil)
2503             (emit 'goto `,label2)
2504             (emit 'label `,label1)
2505             (emit-push-t)
2506             (emit 'label `,label2))
2507           (emit-move-from-stack target)
2508           t)
2509          (LIST
2510           (compile-form first :target :stack)
2511           (compile-form second :target :stack)
2512           (unless (and (single-valued-p first)
2513                        (single-valued-p second))
2514             (emit-clear-values))
2515           (emit-invokestatic +lisp-class+ "list2"
2516                              (list +lisp-object+ +lisp-object+) +lisp-cons+)
2517           (emit-move-from-stack target)
2518           t)
2519          (SYS::%STRUCTURE-REF
2520           (when (fixnump second)
2521             (compile-form first :target :stack)
2522             (maybe-emit-clear-values first)
2523             (emit 'sipush second)
2524             (emit-invokevirtual +lisp-object-class+ "getSlotValue"
2525                                 '("I") +lisp-object+)
2526             (when (eq representation :unboxed-fixnum)
2527               (emit-unbox-fixnum))
2528             (emit-move-from-stack target representation)
2529             t))
2530          (t
2531           nil)))))
2532
2533(defun fixnum-or-unboxed-variable-p (arg)
2534  (or (fixnump arg)
2535      (unboxed-fixnum-variable arg)))
2536
2537(defun emit-push-int (arg)
2538  (if (fixnump arg)
2539      (emit-push-constant-int arg)
2540      (let ((variable (unboxed-fixnum-variable arg)))
2541        (if variable
2542            (emit 'iload (variable-register variable))
2543            (aver nil)))))
2544
2545(defun emit-push-long (arg)
2546  (cond ((eql arg 0)
2547         (emit 'lconst_0))
2548        ((eql arg 1)
2549         (emit 'lconst_1))
2550        ((fixnump arg)
2551         (emit-push-constant-int arg)
2552         (emit 'i2l))
2553        (t
2554         (let ((variable (unboxed-fixnum-variable arg)))
2555           (aver (not (null variable)))
2556           (aver (not (null (variable-register variable))))
2557           (emit 'iload (variable-register variable))
2558           (emit 'i2l)))))
2559
2560(defun p2-eql (form &key (target :stack) representation)
2561  (unless (check-arg-count form 2)
2562    (compile-function-call form target representation)
2563    (return-from p2-eql))
2564  (let ((arg1 (second form))
2565        (arg2 (third form)))
2566    (cond ((and (fixnum-or-unboxed-variable-p arg1)
2567                (fixnum-or-unboxed-variable-p arg2))
2568           (emit-push-int arg1)
2569           (emit-push-int arg2)
2570           (let ((label1 (gensym))
2571                 (label2 (gensym)))
2572             (emit 'if_icmpeq `,label1)
2573             (emit-push-nil)
2574             (emit 'goto `,label2)
2575             (emit 'label `,label1)
2576             (emit-push-t)
2577             (emit 'label `,label2))
2578           (emit-move-from-stack target))
2579          ((fixnum-or-unboxed-variable-p arg1)
2580           (emit-push-int arg1)
2581           (compile-form arg2 :target :stack)
2582           (maybe-emit-clear-values arg2)
2583           (emit 'swap)
2584           (emit-invokevirtual +lisp-object-class+ "eql" '("I") "Z")
2585           (let ((label1 (gensym))
2586                 (label2 (gensym)))
2587             (emit 'ifne `,label1)
2588             (emit-push-nil)
2589             (emit 'goto `,label2)
2590             (emit 'label `,label1)
2591             (emit-push-t)
2592             (emit 'label `,label2))
2593           (emit-move-from-stack target))
2594          ((fixnum-or-unboxed-variable-p arg2)
2595           (compile-form arg1 :target :stack)
2596           (maybe-emit-clear-values arg1)
2597           (emit-push-int arg2)
2598           (emit-invokevirtual +lisp-object-class+ "eql" '("I") "Z")
2599           (let ((label1 (gensym))
2600                 (label2 (gensym)))
2601             (emit 'ifne `,label1)
2602             (emit-push-nil)
2603             (emit 'goto `,label2)
2604             (emit 'label `,label1)
2605             (emit-push-t)
2606             (emit 'label `,label2))
2607           (emit-move-from-stack target))
2608          (t
2609           (compile-form arg1 :target :stack)
2610           (compile-form arg2 :target :stack)
2611           (unless (and (single-valued-p arg1)
2612                        (single-valued-p arg2))
2613             (emit-clear-values))
2614           (emit-invokevirtual +lisp-object-class+ "EQL"
2615                               (list +lisp-object+) +lisp-object+)
2616           (emit-move-from-stack target)))))
2617
2618(defun compile-function-call-3 (op args target)
2619  (case op
2620    (LIST
2621     (compile-form (first args) :target :stack)
2622     (compile-form (second args) :target :stack)
2623     (compile-form (third args) :target :stack)
2624     (unless (every 'single-valued-p args)
2625       (emit-clear-values))
2626     (emit-invokestatic +lisp-class+ "list3"
2627                        (list +lisp-object+ +lisp-object+ +lisp-object+)
2628                        +lisp-cons+)
2629     (emit-move-from-stack target)
2630     t)
2631    (SYS::%STRUCTURE-SET
2632     (when (fixnump (second args))
2633       (compile-form (first args) :target :stack)
2634       (maybe-emit-clear-values (first args))
2635       (emit 'sipush (second args))
2636       (compile-form (third args) :target :stack)
2637       (maybe-emit-clear-values (third args))
2638       (emit-invokevirtual +lisp-object-class+ "setSlotValue"
2639                           (list "I" +lisp-object+) +lisp-object+)
2640       (emit-move-from-stack target)
2641       t))
2642    (t
2643     nil)))
2644
2645(defvar *defined-functions*)
2646
2647(defvar *undefined-functions*)
2648
2649(defun note-name-defined (name)
2650  (when (boundp '*defined-functions*)
2651    (push name *defined-functions*))
2652  (when (boundp '*undefined-functions*)
2653    (setf *undefined-functions* (remove name *undefined-functions*))))
2654
2655(defvar *functions-defined-in-current-file* nil)
2656
2657(defsubst notinline-p (name)
2658  (declare (optimize speed))
2659  (eq (get name '%inline) 'NOTINLINE))
2660
2661(defun inline-ok (name)
2662  (declare (optimize speed))
2663  (cond ((notinline-p name)
2664         nil)
2665        ((sys:built-in-function-p name)
2666         t)
2667        ((memq name *functions-defined-in-current-file*)
2668         t)
2669        (t
2670         nil)))
2671
2672(defun unsafe-p (args)
2673  (cond ((node-p args)
2674         (unsafe-p (node-form args)))
2675        ((atom args)
2676         nil)
2677        (t
2678         (case (car args)
2679           (QUOTE
2680            nil)
2681           (LAMBDA
2682            nil)
2683           ((RETURN-FROM GO CATCH THROW UNWIND-PROTECT BLOCK)
2684            t)
2685           (t
2686            (dolist (arg args)
2687              (when (unsafe-p arg)
2688                (return t))))))))
2689
2690(defun rewrite-function-call (form)
2691  (let ((args (cdr form)))
2692    (if (unsafe-p args)
2693        (let ((syms ())
2694              (lets ()))
2695          ;; Preserve the order of evaluation of the arguments!
2696          (dolist (arg args)
2697            (if (constantp arg)
2698                (push arg syms)
2699                (let ((sym (gensym)))
2700                  (push sym syms)
2701                  (push (list sym arg) lets))))
2702          (list 'LET* (nreverse lets) (list* (car form) (nreverse syms))))
2703        form)))
2704
2705(defun process-args (args)
2706  (let ((numargs (length args)))
2707    (when (plusp numargs)
2708      (let ((must-clear-values nil))
2709        (cond ((<= numargs 4)
2710               (dolist (arg args)
2711                 (compile-form arg :target :stack)
2712                 (unless must-clear-values
2713                   (unless (single-valued-p arg)
2714                     (setf must-clear-values t)))))
2715              (t
2716               (emit 'sipush numargs)
2717               (emit 'anewarray +lisp-object-class+)
2718               (let ((i 0))
2719                 (dolist (arg args)
2720                   (emit 'dup)
2721                   (emit 'sipush i)
2722                   (compile-form arg :target :stack)
2723                   (emit 'aastore) ; store value in array
2724                   (unless must-clear-values
2725                     (unless (single-valued-p arg)
2726                       (setf must-clear-values t)))
2727                   (incf i)))))
2728        (when must-clear-values
2729          (emit-clear-values))))))
2730
2731(defun emit-call-execute (numargs)
2732  (let ((arg-types (if (<= numargs 4)
2733                       (make-list numargs :initial-element +lisp-object+)
2734                       (list +lisp-object-array+)))
2735        (return-type +lisp-object+))
2736    (emit-invokevirtual +lisp-object-class+ "execute" arg-types return-type)))
2737
2738(defun emit-call-thread-execute (numargs)
2739  (let ((arg-types (if (<= numargs 4)
2740                       (make-list (1+ numargs) :initial-element +lisp-object+)
2741                       (list +lisp-object+ +lisp-object-array+)))
2742        (return-type +lisp-object+))
2743    (emit-invokevirtual +lisp-thread-class+ "execute" arg-types return-type)))
2744
2745(defun compile-function-call (form target representation)
2746  (dformat t "compile-function-call ~S representation = ~S~%" (car form) representation)
2747  (let ((op (car form))
2748        (args (cdr form)))
2749    (unless (symbolp op)
2750      (error "COMPILE-FUNCTION-CALL ~S is not a symbol" op))
2751    (when (find-local-function op)
2752      (return-from compile-function-call
2753                   (compile-local-function-call form target representation)))
2754    (when (and (boundp '*defined-functions*) (boundp '*undefined-functions*))
2755      (unless (or (fboundp op)
2756                  (eq op (compiland-name *current-compiland*))
2757                  (memq op *defined-functions*))
2758        (push op *undefined-functions*)))
2759    (let ((numargs (length args)))
2760      (case (length args)
2761        (1
2762         (when (compile-function-call-1 op args target representation)
2763           (return-from compile-function-call)))
2764        (2
2765         (when (compile-function-call-2 op args target representation)
2766           (return-from compile-function-call)))
2767        (3
2768         (when (compile-function-call-3 op args target)
2769           (return-from compile-function-call))))
2770      (unless (> *speed* *debug*)
2771        (emit-push-current-thread))
2772      (cond ((eq op (compiland-name *current-compiland*)) ; recursive call
2773             (if (notinline-p op)
2774                 (emit 'getstatic *this-class* (declare-symbol op) +lisp-symbol+)
2775                 (emit 'aload 0)))
2776            ((inline-ok op)
2777             (emit 'getstatic *this-class* (declare-function op) +lisp-object+))
2778            ((null (symbol-package op))
2779             (let ((g (if *compile-file-truename*
2780                          (declare-object-as-string op)
2781                          (declare-object op))))
2782               (emit 'getstatic *this-class* g +lisp-object+)))
2783            (t
2784             (emit 'getstatic *this-class* (declare-symbol op) +lisp-symbol+)))
2785      (process-args args)
2786      (if (> *speed* *debug*)
2787          (emit-call-execute numargs)
2788          (emit-call-thread-execute numargs))
2789      (when (eq representation :unboxed-fixnum)
2790        (emit-unbox-fixnum))
2791      (emit-move-from-stack target))))
2792
2793(defun compile-call (args)
2794  (let ((numargs (length args)))
2795    (cond ((> *speed* *debug*)
2796           (process-args args)
2797           (emit-call-execute numargs))
2798          (t
2799           (emit-push-current-thread)
2800           (emit 'swap) ; Stack: thread function
2801           (process-args args)
2802           (emit-call-thread-execute numargs)))))
2803
2804(define-source-transform funcall (&whole form fun &rest args)
2805  (cond ((> *debug* *speed*)
2806         form)
2807        ((and (consp fun)
2808              (eq (car fun) 'FUNCTION)
2809              (symbolp (cadr fun)))
2810         `(,(cadr fun) ,@args))
2811        ((and (consp fun)
2812              (eq (car fun) 'QUOTE))
2813         (let ((sym (cadr fun)))
2814           (if (and (symbolp sym)
2815                    (eq (symbol-package sym) (find-package "CL"))
2816                    (not (special-operator-p sym))
2817                    (not (macro-function sym)))
2818               `(,(cadr fun) ,@args)
2819               form)))
2820        (t
2821         form)))
2822
2823(defun compile-funcall (form &key (target :stack) representation)
2824  (unless (> (length form) 1)
2825    (compiler-style-warn "Wrong number of arguments for ~A." (car form))
2826    (compile-function-call form target representation))
2827  (when (> *debug* *speed*)
2828    (return-from compile-funcall (compile-function-call form target representation)))
2829  (compile-form (cadr form) :target :stack)
2830  (maybe-emit-clear-values (cadr form))
2831  (compile-call (cddr form))
2832  (emit-move-from-stack target))
2833
2834(defun save-variables (variables)
2835  (let ((saved-vars '()))
2836    (dolist (variable variables)
2837      (when (variable-closure-index variable)
2838        (let ((register (allocate-register)))
2839          (emit 'aload (compiland-closure-register *current-compiland*))
2840          (emit-push-constant-int (variable-closure-index variable))
2841          (emit 'aaload)
2842          (emit 'astore register)
2843          (push (cons variable register) saved-vars))))
2844    saved-vars))
2845
2846(defun restore-variables (saved-vars)
2847  (dolist (saved-var saved-vars)
2848    (let ((variable (car saved-var))
2849          (register (cdr saved-var)))
2850      (emit 'aload (compiland-closure-register *current-compiland*))
2851      (emit-push-constant-int (variable-closure-index variable))
2852      (emit 'aload register)
2853      (emit 'aastore))))
2854
2855(defun compile-local-function-call (form target representation)
2856  (let* ((compiland *current-compiland*)
2857         (op (car form))
2858         (args (cdr form))
2859         (local-function (find-local-function op))
2860         (*register* *register*)
2861         (saved-vars '()))
2862    (cond ((eq (local-function-compiland local-function) compiland)
2863           ;; Recursive call.
2864           (dformat t "compile-local-function-call recursive case~%")
2865           (setf saved-vars
2866                 (save-variables (compiland-arg-vars (local-function-compiland local-function))))
2867           (emit 'aload_0))
2868          ((local-function-variable local-function)
2869           ;; LABELS
2870           (dformat t "compile-local-function-call LABELS case~%")
2871           (dformat t "save args here: ~S~%"
2872                    (mapcar #'variable-name
2873                            (compiland-arg-vars (local-function-compiland local-function))))
2874           (unless (null (compiland-parent compiland))
2875             (setf saved-vars
2876                   (save-variables (compiland-arg-vars (local-function-compiland local-function)))))
2877           (emit 'var-ref (local-function-variable local-function) :stack))
2878          (t
2879           (dformat t "compile-local-function-call default case~%")
2880           (let* ((g (if *compile-file-truename*
2881                         (declare-local-function local-function)
2882                         (declare-object (local-function-function local-function)))))
2883             (emit 'getstatic *this-class* g +lisp-object+)))) ; Stack: template-function
2884
2885    (when *closure-variables*
2886      (emit 'checkcast +lisp-ctf-class+))
2887
2888    (when *closure-variables*
2889      ;; First arg is closure variable array.
2890      (aver (not (null (compiland-closure-register compiland))))
2891      (emit 'aload (compiland-closure-register compiland)))
2892    (let ((must-clear-values nil))
2893      (cond ((> (length args) 4)
2894             (emit-push-constant-int (length args))
2895             (emit 'anewarray "org/armedbear/lisp/LispObject")
2896             (let ((i 0))
2897               (dolist (arg args)
2898                 (emit 'dup)
2899                 (emit-push-constant-int i)
2900                 (compile-form arg :target :stack)
2901                 (emit 'aastore) ; store value in array
2902                 (unless must-clear-values
2903                   (unless (single-valued-p arg)
2904                     (setf must-clear-values t)))
2905                 (incf i)))) ; array left on stack here
2906            (t
2907             (dolist (arg args)
2908               (compile-form arg :target :stack)
2909               (unless must-clear-values
2910                 (unless (single-valued-p arg)
2911                   (setf must-clear-values t)))))) ; args left on stack here
2912      (when must-clear-values
2913        (emit-clear-values)))
2914
2915    (if *closure-variables*
2916        (let* ((arg-count (length args))
2917               (arg-types (if (<= arg-count 4)
2918                              (list* +lisp-object-array+
2919                                     (make-list arg-count :initial-element +lisp-object+))
2920                              (list +lisp-object-array+ +lisp-object-array+)))
2921               (result-type +lisp-object+))
2922          (emit-invokevirtual +lisp-ctf-class+ "execute" arg-types result-type))
2923        ;; No closure variables.
2924        (let* ((arg-count (length args))
2925               (arg-types (if (<= arg-count 4)
2926                              (make-list arg-count :initial-element +lisp-object+)
2927                              (list +lisp-object-array+)))
2928               (result-type +lisp-object+))
2929          (emit-invokevirtual +lisp-object-class+ "execute" arg-types result-type)))
2930
2931    (when (eq representation :unboxed-fixnum)
2932      (emit-unbox-fixnum))
2933    (emit-move-from-stack target representation)
2934    (when saved-vars
2935      (restore-variables saved-vars))))
2936
2937(defparameter java-predicates (make-hash-table :test 'eq))
2938
2939(defun define-java-predicate (predicate translation)
2940  (setf (gethash predicate java-predicates) translation))
2941
2942(define-java-predicate 'CHARACTERP         "characterp")
2943(define-java-predicate 'CONSTANTP          "constantp")
2944(define-java-predicate 'ENDP               "endp")
2945(define-java-predicate 'EVENP              "evenp")
2946(define-java-predicate 'FLOATP             "floatp")
2947(define-java-predicate 'INTEGERP           "integerp")
2948(define-java-predicate 'LISTP              "listp")
2949(define-java-predicate 'MINUSP             "minusp")
2950(define-java-predicate 'NUMBERP            "numberp")
2951(define-java-predicate 'ODDP               "oddp")
2952(define-java-predicate 'PLUSP              "plusp")
2953(define-java-predicate 'RATIONALP          "rationalp")
2954(define-java-predicate 'REALP              "realp")
2955(define-java-predicate 'STRINGP            "stringp")
2956(define-java-predicate 'SPECIAL-VARIABLE-P "isSpecialVariable")
2957(define-java-predicate 'VECTORP            "vectorp")
2958(define-java-predicate 'ZEROP              "zerop")
2959
2960(defun compile-test-2 (form negatep)
2961  (let* ((op (car form))
2962         (args (cdr form))
2963         (arg (car args))
2964         variable)
2965    (when (memq op '(NOT NULL))
2966      (return-from compile-test-2 (compile-test arg (not negatep))))
2967;;     (when (setf variable (unboxed-fixnum-variable arg))
2968;;       (case op
2969;;         (MINUSP
2970;;          (dformat t "compile-test-2 minusp case~%")
2971;;          (aver (variable-register variable))
2972;;          (emit 'iload (variable-register variable))
2973;;          (return-from compile-test-2 (if negatep 'iflt 'ifge)))))
2974    (when (subtypep (derive-type arg) 'FIXNUM)
2975      (case op
2976        (MINUSP
2977         (dformat t "compile-test-2 minusp case~%")
2978         (compile-form arg :target :stack :representation :unboxed-fixnum)
2979         (return-from compile-test-2 (if negatep 'iflt 'ifge)))
2980        (ZEROP
2981         (dformat t "compile-test-2 zerop case~%")
2982         (compile-form arg :target :stack :representation :unboxed-fixnum)
2983         (return-from compile-test-2 (if negatep 'ifeq 'ifne)))))
2984    (when (eq op 'SYMBOLP)
2985      (process-args args)
2986      (emit 'instanceof +lisp-symbol-class+)
2987      (return-from compile-test-2 (if negatep 'ifne 'ifeq)))
2988    (when (eq op 'FIXNUMP)
2989      (process-args args)
2990      (emit 'instanceof +lisp-fixnum-class+)
2991      (return-from compile-test-2 (if negatep 'ifne 'ifeq)))
2992    (when (eq op 'CONSP)
2993      (process-args args)
2994      (emit 'instanceof +lisp-cons-class+)
2995      (return-from compile-test-2 (if negatep 'ifne 'ifeq)))
2996    (when (eq op 'ATOM)
2997      (process-args args)
2998      (emit 'instanceof +lisp-cons-class+)
2999      (return-from compile-test-2 (if negatep 'ifeq 'ifne)))
3000    (let ((s (gethash op java-predicates)))
3001      (when s
3002        (process-args args)
3003        (emit-invokevirtual +lisp-object-class+ s nil "Z")
3004        (return-from compile-test-2 (if negatep 'ifne 'ifeq)))))
3005  ;; Otherwise...
3006  (compile-form form :target :stack)
3007  (maybe-emit-clear-values form)
3008  (emit-push-nil)
3009  (if negatep 'if_acmpne 'if_acmpeq))
3010
3011(defun p2-numeric-comparison (form &key (target :stack) representation)
3012  (let ((op (car form))
3013        (args (cdr form)))
3014    (case (length args)
3015      (2
3016       (dformat t "p2-numeric-comparison form = ~S~%" form)
3017       (let ((first (first args))
3018             (second (second args))
3019             var1 var2)
3020         (cond ((and (fixnump first) (fixnump second))
3021                (if (funcall op first second)
3022                    (emit-push-t)
3023                    (emit-push-nil))
3024                (emit-move-from-stack target)
3025                (return-from p2-numeric-comparison))
3026               ((and (setf var1 (unboxed-fixnum-variable first))
3027                     (setf var2 (unboxed-fixnum-variable second)))
3028                (dformat t "p2-numeric-comparison both unboxed var case form = ~S~%" form)
3029                (let ((LABEL1 (gensym))
3030                      (LABEL2 (gensym)))
3031                  (emit 'iload (variable-register var1))
3032                  (emit 'iload (variable-register var2))
3033                  (emit (case op
3034                          (<  'if_icmpge)
3035                          (<= 'if_icmpgt)
3036                          (>  'if_icmple)
3037                          (>= 'if_icmplt)
3038                          (=  'if_icmpne)
3039                          (/= 'if_icmpeq))
3040                        LABEL1)
3041                  (emit-push-t)
3042                  (emit 'goto LABEL2)
3043                  (label LABEL1)
3044                  (emit-push-nil)
3045                  (label LABEL2)
3046                  (emit-move-from-stack target)
3047                  (return-from p2-numeric-comparison)))
3048               ((and (subtypep (derive-type first) 'FIXNUM)
3049                     (subtypep (derive-type second) 'FIXNUM))
3050                (let ((LABEL1 (gensym))
3051                      (LABEL2 (gensym)))
3052                  (compile-form first :target :stack :representation :unboxed-fixnum)
3053                  (compile-form second :target :stack :representation :unboxed-fixnum)
3054                  (unless (and (single-valued-p first) (single-valued-p second))
3055                    (emit-clear-values))
3056                  (emit (case op
3057                          (<  'if_icmpge)
3058                          (<= 'if_icmpgt)
3059                          (>  'if_icmple)
3060                          (>= 'if_icmplt)
3061                          (=  'if_icmpne)
3062                          (/= 'if_icmpeq))
3063                        LABEL1)
3064                  (emit-push-t)
3065                  (emit 'goto LABEL2)
3066                  (label LABEL1)
3067                  (emit-push-nil)
3068                  (label LABEL2)
3069                  (emit-move-from-stack target)
3070                  (return-from p2-numeric-comparison)))
3071               ((fixnump second)
3072                (compile-form first :target :stack)
3073                (maybe-emit-clear-values first)
3074                (emit-push-constant-int second)
3075                (emit-invokevirtual +lisp-object-class+
3076                                    (case op
3077                                      (<  "isLessThan")
3078                                      (<= "isLessThanOrEqualTo")
3079                                      (>  "isGreaterThan")
3080                                      (>= "isGreaterThanOrEqualTo")
3081                                      (=  "isEqualTo")
3082                                      (/= "isNotEqualTo"))
3083                                    '("I")
3084                                    "Z")
3085                ;; Java boolean on stack here
3086                (let ((LABEL1 (gensym))
3087                      (LABEL2 (gensym)))
3088                  (emit 'ifeq LABEL1)
3089                  (emit-push-t)
3090                  (emit 'goto LABEL2)
3091                  (label LABEL1)
3092                  (emit-push-nil)
3093                  (label LABEL2)
3094                  (emit-move-from-stack target))
3095                (return-from p2-numeric-comparison))
3096               )))))
3097  ;; Still here?
3098  (compile-function-call form target representation))
3099
3100(defun compile-test-3 (form negatep)
3101  (let ((op (car form))
3102        (args (cdr form)))
3103    (when (eq op 'EQ)
3104      (process-args args)
3105      (return-from compile-test-3 (if negatep 'if_acmpeq 'if_acmpne)))
3106    (let* ((arg1 (first args))
3107           (arg2 (second args))
3108           (var1 (unboxed-fixnum-variable arg1))
3109           (var2 (unboxed-fixnum-variable arg2)))
3110      (when (memq op '(< <= > >= = /=))
3111        (when (and (arg-is-fixnum-p arg1)
3112                   (arg-is-fixnum-p arg2))
3113          (emit-push-int arg1)
3114          (emit-push-int arg2)
3115          (case op
3116            (<
3117             (return-from compile-test-3 (if negatep 'if_icmplt 'if_icmpge)))
3118            (<=
3119             (return-from compile-test-3 (if negatep 'if_icmple 'if_icmpgt)))
3120            (>
3121             (return-from compile-test-3 (if negatep 'if_icmpgt 'if_icmple)))
3122            (>=
3123             (return-from compile-test-3 (if negatep 'if_icmpge 'if_icmplt)))
3124            (=
3125             (return-from compile-test-3 (if negatep 'if_icmpeq 'if_icmpne)))
3126            (/=
3127             (return-from compile-test-3 (if negatep 'if_icmpne 'if_icmpeq)))
3128            ))
3129
3130        ;; Otherwise...
3131        (when (arg-is-fixnum-p arg2)
3132          (compile-form arg1 :target :stack)
3133          (maybe-emit-clear-values arg1)
3134          (emit-push-int arg2)
3135          (emit-invokevirtual +lisp-object-class+
3136                              (case op
3137                                (<  "isLessThan")
3138                                (<= "isLessThanOrEqualTo")
3139                                (>  "isGreaterThan")
3140                                (>= "isGreaterThanOrEqualTo")
3141                                (=  "isEqualTo")
3142                                (/= "isNotEqualTo"))
3143                              '("I")
3144                              "Z")
3145          (return-from compile-test-3 (if negatep 'ifne 'ifeq))))
3146
3147      (when (eq op '<)
3148          (when var1
3149            (dformat t "compile-test-3 unboxed fixnum var1 comparison case~%")
3150            (aver (variable-register var1))
3151            (emit 'iload (variable-register var1))
3152            (compile-form arg2 :target :stack)
3153            (emit 'swap)
3154            (emit-invokevirtual +lisp-object-class+
3155                                "isGreaterThan"
3156                                '("I")
3157                                "Z")
3158            (return-from compile-test-3 (if negatep 'ifne 'ifeq)))))
3159
3160    (let ((s (cdr (assq op
3161                        '((=      . "isEqualTo")
3162                          (/=     . "isNotEqualTo")
3163                          (<      . "isLessThan")
3164                          (<=     . "isLessThanOrEqualTo")
3165                          (>      . "isGreaterThan")
3166                          (>=     . "isGreaterThanOrEqualTo")
3167                          (EQL    . "eql")
3168                          (EQUAL  . "equal")
3169                          (EQUALP . "equalp"))))))
3170      (when s
3171        (let ((first (first args))
3172              (second (second args))
3173              variable)
3174          (cond ((fixnump second)
3175                 (compile-form first :target :stack)
3176                 (maybe-emit-clear-values first)
3177                 (emit-push-constant-int second)
3178                 (emit-invokevirtual +lisp-object-class+ s '("I") "Z"))
3179                ((setf variable (unboxed-fixnum-variable second))
3180                 (compile-form first :target :stack)
3181                 (maybe-emit-clear-values first)
3182                 (aver (variable-register variable))
3183                 (emit 'iload (variable-register variable))
3184                 (emit-invokevirtual +lisp-object-class+ s '("I") "Z"))
3185                (t
3186                 (process-args args)
3187                 (emit-invokevirtual +lisp-object-class+ s (list +lisp-object+) "Z")))
3188          (return-from compile-test-3 (if negatep 'ifne 'ifeq))))))
3189
3190  ;; Otherwise...
3191  (compile-form form :target :stack)
3192  (maybe-emit-clear-values form)
3193  (emit-push-nil)
3194  (if negatep 'if_acmpne 'if_acmpeq))
3195
3196(defun compile-test (form negatep)
3197  ;; Use a Java boolean if possible.
3198  (when (and (consp form)
3199             (not (special-operator-p (car form))))
3200    (case (length form)
3201      (2
3202       (return-from compile-test (compile-test-2 form negatep)))
3203      (3
3204       (return-from compile-test (compile-test-3 form negatep)))))
3205  ;; Otherwise...
3206  (compile-form form :target :stack)
3207  (maybe-emit-clear-values form)
3208  (emit-push-nil)
3209  (if negatep 'if_acmpne 'if_acmpeq))
3210
3211(defun compile-if (form &key (target :stack) representation)
3212  (let* ((test (second form))
3213         (consequent (third form))
3214         (alternate (fourth form))
3215         (LABEL1 (gensym))
3216         (LABEL2 (gensym)))
3217    (cond ((eq test t)
3218           (compile-form consequent :target target :representation representation))
3219          ((null test)
3220           (compile-form alternate :target target :representation representation))
3221          ((numberp test)
3222           (compile-form consequent :target target :representation representation))
3223          (t
3224           (emit (compile-test test nil) LABEL1)
3225           (compile-form consequent :target target :representation representation)
3226           (emit 'goto LABEL2)
3227           (label LABEL1)
3228           (compile-form alternate :target target :representation representation)
3229           (label LABEL2)))))
3230
3231(defun compile-multiple-value-list (form &key (target :stack) representation)
3232  (emit-clear-values)
3233  (compile-form (second form) :target :stack)
3234  (emit-invokestatic +lisp-class+ "multipleValueList"
3235                     (list +lisp-object+) +lisp-object+)
3236  (emit-move-from-stack target))
3237
3238(defun compile-multiple-value-prog1 (form &key (target :stack) representation)
3239  (let ((first-subform (cadr form))
3240        (subforms (cddr form))
3241        (result-register (allocate-register))
3242        (values-register (allocate-register)))
3243    ;; Make sure there are no leftover values from previous calls.
3244    (emit-clear-values)
3245    (compile-form first-subform :target result-register)
3246    ;; Save multiple values returned by first subform.
3247    (emit-push-current-thread)
3248    (emit 'getfield +lisp-thread-class+ "_values" "[Lorg/armedbear/lisp/LispObject;")
3249    (emit 'astore values-register)
3250    (dolist (subform subforms)
3251      (compile-form subform :target nil))
3252    ;; Restore multiple values returned by first subform.
3253    (emit-push-current-thread)
3254    (emit 'aload values-register)
3255    (emit 'putfield +lisp-thread-class+ "_values" "[Lorg/armedbear/lisp/LispObject;")
3256    ;; Result.
3257    (emit 'aload result-register)
3258    (emit-move-from-stack target)))
3259
3260(defun compile-multiple-value-call (form &key (target :stack) representation)
3261  (case (length form)
3262    (1
3263     (error "Wrong number of arguments for MULTIPLE-VALUE-CALL."))
3264    (2
3265     (compile-form (second form) :target :stack)
3266     (emit-invokestatic +lisp-class+ "coerceToFunction"
3267                        (list +lisp-object+) +lisp-object+)
3268     (emit-invokevirtual +lisp-object-class+ "execute" nil +lisp-object+)
3269     (emit-move-from-stack target))
3270    (3
3271     (let* ((*register* *register*)
3272            (function-register (allocate-register)))
3273       (compile-form (second form) :target function-register)
3274       (compile-form (third form) :target :stack)
3275       (emit 'aload function-register)
3276       (emit-push-current-thread)
3277       (emit-invokestatic +lisp-class+ "multipleValueCall1"
3278                          (list +lisp-object+ +lisp-object+ +lisp-thread+)
3279                          +lisp-object+)
3280       (emit-move-from-stack target)))
3281    (t
3282     ;; The general case.
3283     (let* ((*register* *register*)
3284            (function-register (allocate-register))
3285            (values-register (allocate-register)))
3286       (compile-form (second form) :target :stack)
3287       (emit-invokestatic +lisp-class+ "coerceToFunction"
3288                          (list +lisp-object+) +lisp-object+)
3289       (emit-move-from-stack function-register)
3290       (emit 'aconst_null)
3291       (emit 'astore values-register)
3292       (dolist (values-form (cddr form))
3293         (compile-form values-form :target :stack)
3294         (emit-push-current-thread)
3295         (emit 'swap)
3296         (emit 'aload values-register)
3297         (emit-invokevirtual +lisp-thread-class+ "accumulateValues"
3298                             (list +lisp-object+ +lisp-object-array+)
3299                             +lisp-object-array+)
3300         (emit 'astore values-register)
3301         (maybe-emit-clear-values values-form))
3302       (emit 'aload function-register)
3303       (emit 'aload values-register)
3304       (emit-invokevirtual +lisp-object-class+ "execute"
3305                           (list +lisp-object-array+) +lisp-object+)
3306       (emit-move-from-stack target)))))
3307
3308;; Generates code to bind variable to value at top of runtime stack.
3309(defun compile-binding (variable)
3310  (cond ((variable-register variable)
3311         (emit 'astore (variable-register variable)))
3312        ((variable-special-p variable)
3313         (emit-push-current-thread)
3314         (emit 'swap)
3315         (emit 'getstatic *this-class*
3316               (declare-symbol (variable-name variable)) +lisp-symbol+)
3317         (emit 'swap)
3318         (emit-invokevirtual +lisp-thread-class+ "bindSpecial"
3319                             (list +lisp-symbol+ +lisp-object+) nil))
3320        ((variable-closure-index variable)
3321         (emit 'aload (compiland-closure-register *current-compiland*))
3322         (emit 'swap) ; array value
3323         (emit-push-constant-int (variable-closure-index variable))
3324         (emit 'swap) ; array index value
3325         (emit 'aastore))
3326        (t
3327         (aver nil))))
3328
3329(defun p2-m-v-b-node (block target)
3330  (let* ((*blocks* (cons block *blocks*))
3331         (*register* *register*)
3332         (form (block-form block))
3333         (*visible-variables* *visible-variables*)
3334         (specials ())
3335         (vars (second form))
3336         (bind-special-p nil)
3337         (variables (block-vars block)))
3338    (dolist (variable variables)
3339      (let ((special-p (variable-special-p variable)))
3340        (cond (special-p
3341               (setf bind-special-p t))
3342              (t
3343               (unless (variable-closure-index variable)
3344                 (setf (variable-register variable) (allocate-register)))))))
3345    ;; If we're going to bind any special variables...
3346    (when bind-special-p
3347      (dformat t "p2-m-v-b-node lastSpecialBinding~%")
3348      ;; Save current dynamic environment.
3349      (setf (block-environment-register block) (allocate-register))
3350      (emit-push-current-thread)
3351      (emit 'getfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+)
3352      (emit 'astore (block-environment-register block)))
3353    ;; Make sure there are no leftover values from previous calls.
3354    (emit-clear-values)
3355    ;; Bind the variables.
3356    (aver (= (length vars) (length variables)))
3357    (cond ((= (length vars) 1)
3358           (compile-form (third form) :target :stack)
3359           (maybe-emit-clear-values (third form))
3360           (compile-binding (car variables)))
3361          (t
3362           (let* ((*register* *register*)
3363                  (result-register (allocate-register))
3364                  (values-register (allocate-register))
3365                  (LABEL1 (gensym))
3366                  (LABEL2 (gensym)))
3367             ;; Store primary value from values form in result register.
3368             (compile-form (third form) :target result-register)
3369             ;; Store values from values form in values register.
3370             (emit-push-current-thread)
3371             (emit 'getfield +lisp-thread-class+ "_values" "[Lorg/armedbear/lisp/LispObject;")
3372             (emit-move-from-stack values-register)
3373             ;; Did we get just one value?
3374             (emit 'aload values-register)
3375             (emit 'ifnull LABEL1)
3376             ;; Reaching here, we have multiple values (or no values at all). We need
3377             ;; the slow path if we have more variables than values.
3378             (emit 'aload values-register)
3379             (emit 'arraylength)
3380             (emit 'bipush (length vars))
3381             (emit 'if_icmplt LABEL1)
3382             ;; Reaching here, we have enough values for all the variables. We can use
3383             ;; the values we have. This is the fast path.
3384             (emit 'aload values-register)
3385             (emit 'goto LABEL2)
3386             (label LABEL1)
3387             (emit-push-current-thread)
3388             (emit 'aload result-register)
3389             (emit 'bipush (length vars))
3390             (emit-invokevirtual +lisp-thread-class+ "getValues"
3391                                 (list +lisp-object+ "I") +lisp-object-array+)
3392             ;; Values array is now on the stack at runtime.
3393             (label LABEL2)
3394             (let ((index 0))
3395               (dolist (variable variables)
3396                 (when (< index (1- (length vars)))
3397                   (emit 'dup))
3398                 (emit 'bipush index)
3399                 (incf index)
3400                 (emit 'aaload)
3401                 ;; Value is on the runtime stack at this point.
3402                 (compile-binding variable)))
3403             (maybe-emit-clear-values (third form)))))
3404    ;; Make the variables visible for the body forms.
3405    (dolist (variable variables)
3406      (push variable *visible-variables*))
3407    ;; Body.
3408    (compile-progn-body (cdddr form) target)
3409    (when bind-special-p
3410      ;; Restore dynamic environment.
3411      (emit 'aload *thread*)
3412      (emit 'aload (block-environment-register block))
3413      (emit 'putfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+))))
3414
3415(defun p2-let/let*-node (block target)
3416  (let* ((*blocks* (cons block *blocks*))
3417         (*register* *register*)
3418         (form (block-form block))
3419         (*visible-variables* *visible-variables*)
3420         (specialp nil))
3421    ;; Are we going to bind any special variables?
3422    (dolist (variable (block-vars block))
3423      (when (variable-special-p variable)
3424        (setf specialp t)
3425        (return)))
3426    ;; If so...
3427    (when specialp
3428      (dformat t "p2-let/let*-node lastSpecialBinding~%")
3429      ;; Save current dynamic environment.
3430      (setf (block-environment-register block) (allocate-register))
3431      (emit-push-current-thread)
3432      (emit 'getfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+)
3433      (emit 'astore (block-environment-register block)))
3434    (ecase (car form)
3435      (LET
3436       (p2-let-bindings block))
3437      (LET*
3438       (p2-let*-bindings block)))
3439    ;; Make declarations of free specials visible.
3440    (dolist (variable (block-free-specials block))
3441      (push variable *visible-variables*))
3442    ;; Body of LET/LET*.
3443    (compile-progn-body (cddr form) target)
3444    (when specialp
3445      ;; Restore dynamic environment.
3446      (emit 'aload *thread*)
3447      (emit 'aload (block-environment-register block))
3448      (emit 'putfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+))))
3449
3450(defun p2-let-bindings (block)
3451  (dolist (variable (block-vars block))
3452    (unless (variable-special-p variable)
3453      (unless (variable-closure-index variable)
3454        (setf (variable-register variable) (allocate-register)))))
3455  (let ((*register* *register*)
3456        (must-clear-values nil))
3457    ;; Evaluate each initform. If the variable being bound is special, allocate
3458    ;; a temporary register for the result; LET bindings must be done in
3459    ;; parallel, so we can't modify any specials until all the initforms have
3460    ;; been evaluated. Note that we can't just push the values on the stack
3461    ;; because we'll lose JVM stack consistency if there is a non-local
3462    ;; transfer of control from one of the initforms.
3463    (dolist (variable (block-vars block))
3464      (dformat t "variable = ~S writes = ~S~%" (variable-name variable) (variable-writes variable))
3465      (let ((initform (variable-initform variable)))
3466        (cond (initform
3467               (cond ((and *trust-user-type-declarations*
3468                           (variable-register variable)
3469                           (variable-declared-type variable)
3470                           (subtypep (variable-declared-type variable) 'FIXNUM))
3471                      (dformat t "p2-let-bindings declared fixnum case: ~S~%"
3472                               (variable-name variable))
3473                      (setf (variable-representation variable) :unboxed-fixnum)
3474                      (compile-form initform :target :stack :representation :unboxed-fixnum))
3475                     ((and (variable-register variable)
3476                           (eql (variable-writes variable) 0)
3477                           (subtypep (derive-type initform) 'FIXNUM))
3478                      (dformat t "p2-let-bindings read-only fixnum case: ~S~%"
3479                               (variable-name variable))
3480                      (setf (variable-representation variable) :unboxed-fixnum)
3481                      (compile-form initform :target :stack :representation :unboxed-fixnum))
3482                     (t
3483                      (compile-form initform :target :stack)))
3484               (unless must-clear-values
3485                 (unless (single-valued-p initform)
3486                   (setf must-clear-values t))))
3487              (t
3488               (emit-push-nil)))
3489        (cond ((variable-special-p variable)
3490               (emit-move-from-stack (setf (variable-temp-register variable) (allocate-register))))
3491              ((eq (variable-representation variable) :unboxed-fixnum)
3492               (emit 'istore (variable-register variable)))
3493              (t
3494               (compile-binding variable)))))
3495    (when must-clear-values
3496      (emit-clear-values))
3497    ;; Now that all the initforms have been evaluated, move the results from
3498    ;; the temporary registers (if any) to their proper destinations.
3499    (dolist (variable (block-vars block))
3500      (when (variable-temp-register variable)
3501        (aver (variable-special-p variable))
3502        (emit 'aload (variable-temp-register variable))
3503        (compile-binding variable))))
3504  ;; Now make the variables visible.
3505  (dolist (variable (block-vars block))
3506    (push variable *visible-variables*)))
3507
3508(defun p2-let*-bindings (block)
3509  (let ((must-clear-values nil))
3510    ;; Generate code to evaluate initforms and bind variables.
3511    (dolist (variable (block-vars block))
3512      (let* ((initform (variable-initform variable))
3513             (boundp nil))
3514        (cond ((and (variable-special-p variable)
3515                    (eq initform (variable-name variable)))
3516               (emit-push-current-thread)
3517               (emit 'getstatic *this-class*
3518                     (declare-symbol (variable-name variable)) +lisp-symbol+)
3519               (emit-invokevirtual +lisp-thread-class+
3520                                   "bindSpecialToCurrentValue"
3521                                   (list +lisp-symbol+)
3522                                   nil)
3523               (setf boundp t))
3524              (initform
3525               (cond ((and *trust-user-type-declarations*
3526                           (null (variable-closure-index variable))
3527                           (not (variable-special-p variable))
3528                           (variable-declared-type variable)
3529                           (subtypep (variable-declared-type variable) 'FIXNUM))
3530                      (dformat t "p2-let*-bindings declared fixnum case~%")
3531                      (setf (variable-representation variable) :unboxed-fixnum)
3532                      (compile-form initform :target :stack :representation :unboxed-fixnum)
3533                      (setf (variable-register variable) (allocate-register))
3534                      (emit 'istore (variable-register variable))
3535                      (setf boundp t))
3536                     ((and (null (variable-closure-index variable))
3537                           (not (variable-special-p variable))
3538                           (eql (variable-writes variable) 0)
3539                           (subtypep (derive-type initform) 'FIXNUM))
3540                      (dformat t "p2-let*-bindings read-only fixnum case: ~S~%"
3541                               (variable-name variable))
3542                      (setf (variable-representation variable) :unboxed-fixnum)
3543                      (compile-form initform :target :stack :representation :unboxed-fixnum)
3544                      (setf (variable-register variable) (allocate-register))
3545                      (emit 'istore (variable-register variable))
3546                      (setf boundp t))
3547                     (t
3548                      (compile-form initform :target :stack)))
3549               (unless must-clear-values
3550                 (unless (single-valued-p initform)
3551                   (setf must-clear-values t))))
3552              (t
3553               (emit-push-nil)))
3554        (unless (variable-special-p variable)
3555          (unless (or (variable-closure-index variable) (variable-register variable))
3556            (setf (variable-register variable) (allocate-register))))
3557        (push variable *visible-variables*)
3558        (unless boundp
3559          (compile-binding variable))))
3560    (when must-clear-values
3561      (emit-clear-values))))
3562
3563;; Returns list of declared specials.
3564(defun process-special-declarations (forms)
3565  (let ((specials ()))
3566    (dolist (form forms)
3567      (unless (and (consp form) (eq (car form) 'declare))
3568        (return))
3569      (let ((decls (cdr form)))
3570        (dolist (decl decls)
3571          (when (eq (car decl) 'special)
3572            (setf specials (append (cdr decl) specials))))))
3573    specials))
3574
3575(defun compile-locally (form &key (target :stack) representation)
3576  (let ((*visible-variables* *visible-variables*)
3577        (specials (process-special-declarations (cdr form))))
3578    (dolist (var specials)
3579      (push (make-variable :name var :special-p t) *visible-variables*))
3580    (cond ((null (cdr form))
3581           (when target
3582             (emit-push-nil)
3583             (emit-move-from-stack target)))
3584          (t
3585           (do ((forms (cdr form) (cdr forms)))
3586               ((null forms))
3587             (compile-form (car forms) :target (if (cdr forms) nil target)))))))
3588
3589(defun find-tag (name)
3590  (dolist (tag *visible-tags*)
3591    (when (eql name (tag-name tag))
3592      (return tag))))
3593
3594(defun p2-tagbody-node (block target)
3595  (let* ((*blocks* (cons block *blocks*))
3596         (*visible-tags* *visible-tags*)
3597         (*register* *register*)
3598         (form (block-form block))
3599         (body (cdr form))
3600         (local-tags ())
3601         (BEGIN-BLOCK (gensym))
3602         (END-BLOCK (gensym))
3603         (EXIT (gensym))
3604         environment-register
3605         (must-clear-values nil))
3606    ;; Scan for tags.
3607    (dolist (subform body)
3608      (when (or (symbolp subform) (integerp subform))
3609        (let* ((tag (make-tag :name subform :label (gensym) :block block)))
3610          (push tag local-tags)
3611          (push tag *visible-tags*))))
3612    (when (block-non-local-go-p block)
3613      (dformat t "p2-tagbody-node lastSpecialBinding~%")
3614      (setf environment-register (allocate-register))
3615      (emit-push-current-thread)
3616      (emit 'getfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+)
3617      (emit 'astore environment-register))
3618    (label BEGIN-BLOCK)
3619    (do* ((rest body (cdr rest))
3620          (subform (car rest) (car rest)))
3621         ((null rest))
3622      (cond ((or (symbolp subform) (integerp subform))
3623             (let ((tag (find-tag subform)))
3624               (unless tag
3625                 (error "COMPILE-TAGBODY: tag not found: ~S~%" subform))
3626               (label (tag-label tag))))
3627            (t
3628             (when (and (null (cdr rest)) ;; Last subform.
3629                        (consp subform)
3630                        (eq (car subform) 'GO))
3631               (maybe-generate-interrupt-check))
3632             (compile-form subform :target nil)
3633             (unless must-clear-values
3634               (unless (single-valued-p subform)
3635                 (setf must-clear-values t))))))
3636    (label END-BLOCK)
3637    (emit 'goto EXIT)
3638    (when (block-non-local-go-p block)
3639      ; We need a handler to catch non-local GOs.
3640      (let* ((HANDLER (gensym))
3641             (*register* *register*)
3642             (go-register (allocate-register))
3643             (tag-register (allocate-register)))
3644        (label HANDLER)
3645        ;; The Go object is on the runtime stack. Stack depth is 1.
3646        (emit 'dup)
3647        (emit 'astore go-register)
3648        ;; Get the tag.
3649        (emit 'checkcast +lisp-go-class+)
3650        (emit 'getfield +lisp-go-class+ "tag" +lisp-object+) ; Stack depth is still 1.
3651        (emit 'astore tag-register)
3652        (dolist (tag local-tags)
3653          (let ((NEXT (gensym)))
3654            (emit 'aload tag-register)
3655            (emit 'getstatic *this-class*
3656                  (if *compile-file-truename*
3657                      (declare-object-as-string (tag-label tag))
3658                      (declare-object (tag-label tag)))
3659                  +lisp-object+)
3660            (emit 'if_acmpne NEXT) ;; Jump if not EQ.
3661            ;; Restore dynamic environment.
3662            (emit-push-current-thread)
3663            (aver (fixnump environment-register))
3664            (emit 'aload environment-register)
3665            (emit 'putfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+)
3666            (emit 'goto (tag-label tag))
3667            (label NEXT)))
3668        ;; Not found. Re-throw Go.
3669        (emit 'aload go-register)
3670        (emit 'athrow)
3671        ;; Finally...
3672        (push (make-handler :from BEGIN-BLOCK
3673                            :to END-BLOCK
3674                            :code HANDLER
3675                            :catch-type (pool-class +lisp-go-class+))
3676              *handlers*)))
3677    (label EXIT)
3678    (when must-clear-values
3679      (emit-clear-values))
3680    ;; TAGBODY returns NIL.
3681    (when target
3682      (emit-push-nil)
3683      (emit-move-from-stack target))))
3684
3685(defun p2-go (form &key target representation)
3686  (let* ((name (cadr form))
3687         (tag (find-tag name)))
3688    (unless tag
3689      (error "p2-go: tag not found: ~S" name))
3690    (when (eq (tag-compiland tag) *current-compiland*)
3691      ;; Local case.
3692      (let* ((tag-block (tag-block tag))
3693             (register nil)
3694             (protected
3695              ;; Does the GO leave an enclosing UNWIND-PROTECT?
3696              (dolist (enclosing-block *blocks*)
3697                (when (eq enclosing-block tag-block)
3698                  (return nil))
3699                (when (equal (block-name enclosing-block) '(UNWIND-PROTECT))
3700                  (return t)))))
3701        (unless protected
3702          (dolist (block *blocks*)
3703            (if (eq block tag-block)
3704                (return)
3705                (setf register (or (block-environment-register block) register))))
3706          (when register
3707            ;; Restore dynamic environment.
3708            (emit 'aload *thread*)
3709            (emit 'aload register)
3710            (emit 'putfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+))
3711
3712          ;; FIXME Not exactly the right place for this, but better than nothing.
3713          (maybe-generate-interrupt-check)
3714
3715          (emit 'goto (tag-label tag))
3716          (return-from p2-go))))
3717
3718    ;; Non-local GO.
3719    (emit 'new +lisp-go-class+)
3720    (emit 'dup)
3721    (compile-form `',(tag-label tag) :target :stack) ; Tag.
3722    (emit-invokespecial-init +lisp-go-class+ (list +lisp-object+))
3723    (emit 'athrow)
3724    ;; Following code will not be reached, but is needed for JVM stack
3725    ;; consistency.
3726    (when target
3727      (emit-push-nil)
3728      (emit-move-from-stack target))))
3729
3730(defun p2-atom (form &key (target :stack) representation)
3731  (unless (check-arg-count form 1)
3732    (compile-function-call form target representation)
3733    (return-from p2-atom))
3734  (compile-form (cadr form) :target :stack)
3735  (maybe-emit-clear-values (cadr form))
3736  (emit 'instanceof +lisp-cons-class+)
3737  (let ((LABEL1 (gensym))
3738        (LABEL2 (gensym)))
3739    (emit 'ifeq LABEL1)
3740    (emit-push-nil)
3741    (emit 'goto LABEL2)
3742    (label LABEL1)
3743    (emit-push-t)
3744    (label LABEL2)
3745    (emit-move-from-stack target)))
3746
3747(defun p2-block-node (block target)
3748  (unless (block-node-p block)
3749    (%format t "type-of block = ~S~%" (type-of block))
3750    (aver (block-node-p block)))
3751  (let* ((*blocks* (cons block *blocks*))
3752         (*register* *register*))
3753    (setf (block-target block) target)
3754    (when (block-return-p block)
3755      (dformat t "p2-block-node lastSpecialBinding~%")
3756      (dformat t "*all-variables* = ~S~%" (mapcar #'variable-name *all-variables*))
3757      (cond ((some #'variable-special-p *all-variables*)
3758;;              Save current dynamic environment.
3759             (setf (block-environment-register block) (allocate-register))
3760             (emit-push-current-thread)
3761             (emit 'getfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+)
3762             (emit 'astore (block-environment-register block)))
3763            (t
3764             (dformat t "no specials~%"))))
3765    (setf (block-catch-tag block) (gensym))
3766    (let* ((*register* *register*)
3767           (BEGIN-BLOCK (gensym))
3768           (END-BLOCK (gensym))
3769           (BLOCK-EXIT (block-exit block)))
3770      (label BEGIN-BLOCK) ; Start of protected range.
3771      ;; Implicit PROGN.
3772      (compile-progn-body (cddr (block-form block)) target)
3773      (label END-BLOCK) ; End of protected range.
3774      (emit 'goto BLOCK-EXIT) ; Jump over handler (if any).
3775      (when (block-non-local-return-p block)
3776        ; We need a handler to catch non-local RETURNs.
3777        (let ((HANDLER (gensym))
3778              (RETHROW (gensym)))
3779          (label HANDLER)
3780          ;; The Return object is on the runtime stack. Stack depth is 1.
3781          (emit 'dup) ; Stack depth is 2.
3782          (emit 'getfield +lisp-return-class+ "tag" +lisp-object+) ; Still 2.
3783          (compile-form `',(block-catch-tag block) :target :stack) ; Tag. Stack depth is 3.
3784          ;; If it's not the tag we're looking for...
3785          (emit 'if_acmpne RETHROW) ; Stack depth is 1.
3786          (emit 'getfield +lisp-return-class+ "result" +lisp-object+)
3787          (emit-move-from-stack target) ; Stack depth is 0.
3788          (emit 'goto BLOCK-EXIT)
3789          (label RETHROW)
3790          ;; Not the tag we're looking for.
3791          (emit 'athrow)
3792          ;; Finally...
3793          (push (make-handler :from BEGIN-BLOCK
3794                              :to END-BLOCK
3795                              :code HANDLER
3796                              :catch-type (pool-class +lisp-return-class+))
3797                *handlers*)))
3798      (label BLOCK-EXIT))
3799    (when (block-environment-register block)
3800      ;; We saved the dynamic environment above. Restore it now.
3801      (emit 'aload *thread*)
3802      (emit 'aload (block-environment-register block))
3803      (emit 'putfield +lisp-thread-class+ "lastSpecialBinding" +lisp-binding+))))
3804
3805(defun p2-return-from (form &key (target :stack) representation)
3806  (let* ((name (second form))
3807         (result-form (third form))
3808         (block (find-block name)))
3809    (when (null block)
3810      (error "No block named ~S is currently visible." name))
3811
3812    (dformat t "p2-return-from block = ~S~%" (block-name block))
3813
3814    (when (eq (block-compiland block) *current-compiland*)
3815      (dformat t "p2-return-from *blocks* = ~S~%" (mapcar #'block-name *blocks*))
3816      ;; Local case. Is the RETURN nested inside an UNWIND-PROTECT which
3817      ;; is inside the block we're returning from?
3818      (let ((protected
3819             (dolist (enclosing-block *blocks*)
3820               (when (eq enclosing-block block)
3821                 (return nil))
3822               (when (equal (block-name enclosing-block) '(UNWIND-PROTECT))
3823                 (return t)))))
3824        (dformat t "p2-return-from protected = ~S~%" protected)
3825        (unless protected
3826          (emit-clear-values)
3827          (compile-form result-form :target (block-target block))
3828          (emit 'goto (block-exit block))
3829          (return-from p2-return-from))))
3830
3831    ;; Non-local RETURN.
3832    (aver (block-non-local-return-p block))
3833    (cond ((node-constant-p result-form)
3834           (emit 'new +lisp-return-class+)
3835           (emit 'dup)
3836           (compile-form `',(block-catch-tag block) :target :stack) ; Tag.
3837           (emit-clear-values)
3838           (compile-form result-form :target :stack)) ; Result.
3839          (t
3840           (let* ((*register* *register*)
3841                  (temp-register (allocate-register)))
3842             (emit-clear-values)
3843             (compile-form result-form :target temp-register) ; Result.
3844             (emit 'new +lisp-return-class+)
3845             (emit 'dup)
3846             (compile-form `',(block-catch-tag block) :target :stack) ; Tag.
3847             (emit 'aload temp-register))))
3848    (emit-invokespecial-init +lisp-return-class+ (list +lisp-object+ +lisp-object+))
3849    (emit 'athrow)
3850    ;; Following code will not be reached, but is needed for JVM stack
3851    ;; consistency.
3852    (when target
3853      (emit-push-nil)
3854      (emit-move-from-stack target))))
3855
3856(defun p2-cons (form &key (target :stack) representation)
3857  (unless (check-arg-count form 2)
3858    (compile-function-call form target representation)
3859    (return-from p2-cons))
3860  (emit 'new +lisp-cons-class+)
3861  (emit 'dup)
3862  (process-args (cdr form))
3863  (emit-invokespecial-init +lisp-cons-class+ (list +lisp-object+ +lisp-object+))
3864  (emit-move-from-stack target))
3865
3866(defun compile-progn-body (body target)
3867  (cond ((null body)
3868         (when target
3869           (emit-push-nil)
3870           (emit-move-from-stack target)))
3871        (t
3872         (let ((must-clear-values nil))
3873           (do* ((forms body (cdr forms))
3874                 (form (car forms) (car forms)))
3875                ((null forms))
3876             (when (null (cdr forms))
3877               ;; Last form.
3878               (when must-clear-values
3879                 (emit-clear-values)))
3880             (compile-form form :target (if (cdr forms) nil target))
3881             (unless (null (cdr forms))
3882               (unless must-clear-values
3883                 (unless (single-valued-p form)
3884                   (setf must-clear-values t)))))))))
3885
3886(defun compile-progn (form &key (target :stack) representation)
3887  (compile-progn-body (cdr form) target)
3888  (when (eq representation :unboxed-fixnum)
3889    (emit-unbox-fixnum)))
3890
3891(defun p2-eval-when (form &key (target :stack) representation)
3892  (cond ((or (memq :execute (cadr form))
3893             (memq 'eval (cadr form)))
3894         (compile-progn-body (cddr form) target)
3895         (when (eq representation :unboxed-fixnum)
3896           (emit-unbox-fixnum)))
3897        (t
3898         (emit-push-nil)
3899         (emit-move-from-stack target))))
3900
3901(defun p2-load-time-value (form &key (target :stack) representation)
3902  (cond (*compile-file-truename*
3903         (emit 'getstatic *this-class*
3904               (declare-load-time-value (second form)) +lisp-object+))
3905        (t
3906         (compile-constant (eval (second form))
3907                           :target target
3908                           :representation representation))))
3909
3910(defun compile-quote (form &key (target :stack) representation)
3911   (let ((obj (second form)))
3912     (cond ((null obj)
3913            (when target
3914              (emit-push-nil)
3915              (emit-move-from-stack target)))
3916           ((symbolp obj)
3917            (if (symbol-package obj)
3918                (let ((g (declare-symbol obj)))
3919                  (emit 'getstatic *this-class* g +lisp-symbol+))
3920                ;; An uninterned symbol.
3921                (let ((g (if *compile-file-truename*
3922                             (declare-object-as-string obj)
3923                             (declare-object obj))))
3924                  (emit 'getstatic *this-class* g +lisp-object+)))
3925            (emit-move-from-stack target))
3926           ((listp obj)
3927            (let ((g (if *compile-file-truename*
3928                         (declare-object-as-string obj)
3929                         (declare-object obj))))
3930              (emit 'getstatic *this-class* g +lisp-object+)
3931              (emit-move-from-stack target)))
3932           ((constantp obj)
3933            (compile-constant obj :target target))
3934           (t
3935            (compiler-unsupported "COMPILE-QUOTE: unsupported case: ~S" form)))))
3936
3937(defun p2-rplacd (form &key (target :stack) representation)
3938  (unless (check-arg-count form 2)
3939    (compile-function-call form target representation)
3940    (return-from p2-rplacd))
3941  (let ((args (cdr form)))
3942    (compile-form (first args) :target :stack)
3943    (when target
3944      (emit 'dup))
3945    (compile-form (second args) :target :stack)
3946    (emit-invokevirtual +lisp-object-class+
3947                        "setCdr"
3948                        (list +lisp-object+)
3949                        nil)
3950    (when target
3951      (emit-move-from-stack target))))
3952
3953(defun compile-declare (form &key target representation)
3954  (when target
3955    (emit-push-nil)
3956    (emit-move-from-stack target)))
3957
3958(defun p2-local-function (compiland local-function)
3959  (let ((lambda-list (cadr (compiland-lambda-expression compiland))))
3960    (when (or (memq '&optional lambda-list)
3961              (memq '&key lambda-list))
3962      (let ((state nil))
3963        (dolist (arg lambda-list)
3964          (cond ((memq arg lambda-list-keywords)
3965                 (setf state arg))
3966                ((memq state '(&optional &key))
3967                 (when (and (consp arg)
3968                            (not (constantp (second arg))))
3969                   (compiler-unsupported "P2-LOCAL-FUNCTION: can't handle optional argument with non-constant initform.")))))))
3970    (let* ((name (compiland-name compiland))
3971           form
3972           function
3973           pathname
3974           class-file)
3975      (setf form (compiland-lambda-expression compiland))
3976      (setf pathname (if *compile-file-truename*
3977                         (sys::next-classfile-name)
3978                         (prog1
3979                           (%format nil "local-~D.class" *child-count*)
3980                           (incf *child-count*))))
3981
3982      (setf class-file (make-class-file :pathname pathname
3983                                        :lambda-list lambda-list))
3984
3985      (setf (compiland-class-file compiland) class-file)
3986
3987      (with-class-file class-file
3988        (let ((*current-compiland* compiland)
3989              (*speed* *speed*)
3990              (*safety* *safety*)
3991              (*debug* *debug*))
3992          (p2-compiland compiland)
3993          (write-class-file (compiland-class-file compiland))
3994          ))
3995      (cond (*compile-file-truename*
3996             ;; Verify that the class file is loadable.
3997             (let ((*default-pathname-defaults* pathname))
3998               (unless (ignore-errors (sys:load-compiled-function pathname))
3999                 (error "P2-LOCAL-FUNCTION: unable to load ~S." pathname))))
4000            (t (setf function (sys:load-compiled-function pathname))))
4001      (cond (local-function
4002             (setf (local-function-class-file local-function) class-file)
4003             (let ((g (if *compile-file-truename*
4004                          (declare-local-function local-function)
4005                          (declare-object function))))
4006               (emit 'getstatic *this-class* g +lisp-object+)
4007               (emit 'var-set (local-function-variable local-function))))
4008            (t
4009             (push (make-local-function :name name
4010                                        :function function
4011                                        :class-file class-file)
4012                   *local-functions*))))))
4013
4014(defun p2-flet (form &key (target :stack) representation)
4015  (let ((*local-functions* *local-functions*)
4016        (compilands (cadr form))
4017        (body (cddr form)))
4018    (dolist (compiland compilands)
4019      (p2-local-function compiland nil))
4020    (do ((forms body (cdr forms)))
4021        ((null forms))
4022      (compile-form (car forms) :target (if (cdr forms) nil target)))))
4023
4024(defun p2-labels (form &key target representation)
4025  (let ((*local-functions* *local-functions*)
4026        (local-functions (cadr form))
4027        (body (cddr form)))
4028    (dolist (local-function local-functions)
4029      (push local-function *local-functions*)
4030      (push (local-function-variable local-function) *visible-variables*))
4031    (dolist (local-function local-functions)
4032      (let ((variable (local-function-variable local-function)))
4033        (aver (null (variable-register variable)))
4034        (unless (variable-closure-index variable)
4035          (setf (variable-register variable) (allocate-register)))))
4036    (dolist (local-function local-functions)
4037      (p2-local-function (local-function-compiland local-function) local-function))
4038    (do ((forms body (cdr forms)))
4039        ((null forms))
4040      (compile-form (car forms) :target (if (cdr forms) nil target)))))
4041
4042(defun p2-lambda (compiland target)
4043  (let* ((lambda-list (cadr (compiland-lambda-expression compiland))))
4044    (when (or (memq '&optional lambda-list)
4045              (memq '&key lambda-list))
4046      (let ((state nil))
4047        (dolist (arg lambda-list)
4048          (cond ((memq arg lambda-list-keywords)
4049                 (setf state arg))
4050                ((memq state '(&optional &key))
4051                 (when (and (consp arg)
4052                            (not (constantp (second arg))))
4053                   (compiler-unsupported
4054                    "P2-LAMBDA: can't handle optional argument with non-constant initform.")))))))
4055    (aver (null (compiland-class-file compiland)))
4056    (setf (compiland-class-file compiland)
4057          (make-class-file :pathname (if *compile-file-truename*
4058                                         (sys::next-classfile-name)
4059                                         (prog1
4060                                           (%format nil "local-~D.class" *child-count*)
4061                                           (incf *child-count*)))
4062                           :lambda-list lambda-list)))
4063  (with-class-file (compiland-class-file compiland)
4064    (let ((*current-compiland* compiland)
4065          (*speed* *speed*)
4066          (*safety* *safety*)
4067          (*debug* *debug*))
4068      (p2-compiland compiland)
4069      (write-class-file (compiland-class-file compiland))
4070      ))
4071  (let ((class-file (compiland-class-file compiland)))
4072    (emit 'getstatic *this-class*
4073          (if *compile-file-truename*
4074              (declare-local-function (make-local-function :class-file class-file))
4075              (declare-object (sys:load-compiled-function (class-file-pathname class-file))))
4076          +lisp-object+))
4077  (cond ((null *closure-variables*)) ; Nothing to do.
4078        ((compiland-closure-register *current-compiland*)
4079         (emit 'aload (compiland-closure-register *current-compiland*))
4080         (emit-invokestatic +lisp-class+ "makeCompiledClosure"
4081                            (list +lisp-object+ +lisp-object-array+)
4082                            +lisp-object+)
4083         (emit 'checkcast +lisp-compiled-closure-class+)) ; Stack: compiled-closure
4084        (t
4085         (aver nil))) ;; Shouldn't happen.
4086  (emit-move-from-stack target))
4087
4088(defun p2-function (form &key (target :stack) representation)
4089  (let ((name (second form))
4090        (local-function))
4091    (cond ((symbolp name)
4092           (cond ((setf local-function (find-local-function name))
4093                  (dformat t "p2-function 1~%")
4094                  (when (eq (local-function-compiland local-function) *current-compiland*)
4095                    (emit 'aload 0) ; this
4096                    (emit-move-from-stack target)
4097                    (return-from p2-function))
4098                  (cond ((local-function-variable local-function)
4099                         (dformat t "p2-function 2~%")
4100                         (emit 'var-ref (local-function-variable local-function) :stack))
4101                        (t
4102                         (let ((g (if *compile-file-truename*
4103                                      (declare-local-function local-function)
4104                                      (declare-object (local-function-function local-function)))))
4105                           (emit 'getstatic *this-class*
4106                                 g +lisp-object+)))) ; Stack: template-function
4107                  (cond ((null *closure-variables*)) ; Nothing to do.
4108                        ((compiland-closure-register *current-compiland*)
4109                         (dformat t "p2-function 3~%")
4110                         (emit 'aload (compiland-closure-register *current-compiland*))
4111                         (emit-invokestatic +lisp-class+ "makeCompiledClosure"
4112                                            (list +lisp-object+ +lisp-object-array+)
4113                                            +lisp-object+)) ; Stack: compiled-closure
4114                        (t
4115                         (aver (progn 'unexpected nil))))
4116                  (emit-move-from-stack target))
4117                 ((inline-ok name)
4118                  (emit 'getstatic *this-class*
4119                        (declare-function name) +lisp-object+)
4120                  (emit-move-from-stack target))
4121                 (t
4122                  (emit 'getstatic *this-class*
4123                        (declare-symbol name) +lisp-symbol+)
4124                  (emit-invokevirtual +lisp-object-class+ "getSymbolFunctionOrDie"
4125                                      nil +lisp-object+)
4126                  (emit-move-from-stack target))))
4127          ((and (consp name) (eq (car name) 'SETF))
4128           ; FIXME Need to check for NOTINLINE declaration!
4129           (cond ((member name *functions-defined-in-current-file* :test #'equal)
4130                  (emit 'getstatic *this-class*
4131                        (declare-setf-function name) +lisp-object+)
4132                  (emit-move-from-stack target))
4133                 ((and (null *compile-file-truename*)
4134                       (fdefinition name))
4135                  (emit 'getstatic *this-class*
4136                        (declare-object (fdefinition name)) +lisp-object+)
4137                  (emit-move-from-stack target))
4138                 (t
4139                  (emit 'getstatic *this-class*
4140                        (declare-symbol (cadr name)) +lisp-symbol+)
4141                  (emit-invokevirtual +lisp-symbol-class+
4142                                      "getSymbolSetfFunctionOrDie"
4143                                      nil +lisp-object+)
4144                  (emit-move-from-stack target))))
4145          ((compiland-p name)
4146           (p2-lambda name target))
4147          (t
4148           (compiler-unsupported "p2-function: unsupported case: ~S" form)))))
4149
4150(defun p2-ash (form &key (target :stack) representation)
4151  (dformat t "p2-ash form = ~S representation = ~S~%" form representation)
4152  (unless (check-arg-count form 2)
4153    (compile-function-call form target representation)
4154    (return-from p2-ash))
4155  (let* ((args (cdr form))
4156         (len (length args))
4157         (arg1 (first args))
4158         (arg2 (second args))
4159         (var1 (unboxed-fixnum-variable arg1))
4160         (var2 (unboxed-fixnum-variable arg2)))
4161    (cond ((and (numberp arg1) (numberp arg2))
4162           (dformat t "p2-ash case 1~%")
4163           (compile-constant (ash arg1 arg2)
4164                             :target target
4165                             :representation representation))
4166          ((and var1 (fixnump arg2) (< 0 arg2 32))
4167           (dformat t "p2-ash case 2~%")
4168           (case representation
4169             (:unboxed-fixnum
4170              (emit-push-int var1)
4171              (emit-push-constant-int arg2)
4172              (emit 'ishl))
4173             (t
4174              (emit-push-int var1)
4175              (emit 'i2l)
4176              (emit-push-constant-int arg2)
4177              (emit 'lshl)
4178              (emit-box-long)))
4179           (emit-move-from-stack target representation))
4180          ((and var1 (fixnump arg2) (< -32 arg2 0))
4181           (dformat t "p2-ash case 3~%")
4182           (unless (eq representation :unboxed-fixnum)
4183             (emit 'new +lisp-fixnum-class+)
4184             (emit 'dup))
4185           (emit-push-int var1)
4186           (emit-push-constant-int (- arg2))
4187           (emit 'ishr)
4188           (unless (eq representation :unboxed-fixnum)
4189             (emit-invokespecial-init +lisp-fixnum-class+ '("I")))
4190           (emit-move-from-stack target representation))
4191          (var2
4192           (dformat t "p2-ash case 4~%")
4193           (compile-form arg1 :target :stack)
4194           (maybe-emit-clear-values arg1)
4195           (emit 'iload (variable-register var2))
4196           (emit-invokevirtual +lisp-object-class+ "ash" '("I") +lisp-object+)
4197           (when (eq representation :unboxed-fixnum)
4198             (emit-unbox-fixnum))
4199           (emit-move-from-stack target representation))
4200          ((fixnump arg2)
4201           (dformat t "p2-ash case 5~%")
4202           (compile-form arg1 :target :stack)
4203           (maybe-emit-clear-values arg1)
4204           (emit-push-constant-int arg2)
4205           (emit-invokevirtual +lisp-object-class+ "ash" '("I") +lisp-object+)
4206           (when (eq representation :unboxed-fixnum)
4207             (emit-unbox-fixnum))
4208           (emit-move-from-stack target representation))
4209          (t (dformat t "p2-ash case 6~%")
4210             (compile-function-call form target representation)))))
4211
4212(defun p2-logand (form &key (target :stack) representation)
4213  (let* ((args (cdr form))
4214         (len (length args)))
4215    (when (= len 2)
4216      (let* ((arg1 (first args))
4217             (arg2 (second args))
4218             (var1 (unboxed-fixnum-variable arg1)))
4219        (dformat t "p2-logand var1 = ~S~%" var1)
4220        (dformat t "p2-logand type-of arg2 is ~S~%" (type-of arg2))
4221        (cond ((and (integerp arg1) (integerp arg2))
4222               (dformat t "p2-logand case 1~%")
4223               (compile-constant (logand arg1 arg2) :target target :representation representation)
4224               (return-from p2-logand t))
4225              ((and (fixnump arg2) (zerop arg2))
4226               (dformat t "p2-logand case 2~%")
4227               (compile-constant 0 :target target :representation representation)
4228               (return-from p2-logand t))
4229              ((and var1 (fixnump arg2))
4230               (dformat t "p2-logand case 3~%")
4231               (unless (eq representation :unboxed-fixnum)
4232                 (emit 'new +lisp-fixnum-class+)
4233                 (emit 'dup))
4234               (emit 'iload (variable-register var1))
4235               (emit-push-constant-int arg2)
4236               (emit 'iand)
4237               (unless (eq representation :unboxed-fixnum)
4238                 (emit-invokespecial-init +lisp-fixnum-class+ '("I")))
4239               (emit-move-from-stack target representation)
4240               (return-from p2-logand t))
4241              ((fixnump arg2)
4242               (dformat t "p2-logand case 4~%")
4243               (let ((type (derive-type arg1)))
4244                 (dformat t "p2-logand arg1 derived type = ~S~%" type)
4245                 (cond ((subtypep type 'fixnum)
4246                        (dformat t "p2-logand case 4a~%")
4247                        (unless (eq representation :unboxed-fixnum)
4248                          (emit 'new +lisp-fixnum-class+)
4249                          (emit 'dup))
4250                        (compile-form arg1 :target :stack :representation :unboxed-fixnum)
4251                        (maybe-emit-clear-values arg1)
4252                        (emit-push-constant-int arg2)
4253                        (emit 'iand)
4254                        (unless (eq representation :unboxed-fixnum)
4255                          (emit-invokespecial-init +lisp-fixnum-class+ '("I")))
4256                        (emit-move-from-stack target representation))
4257                       (t (dformat t "p2-logand case 4b~%")
4258                          (compile-form arg1 :target :stack)
4259                          (maybe-emit-clear-values arg1)
4260                          (emit-push-constant-int arg2)
4261                          (emit-invokevirtual +lisp-object-class+ "logand" '("I") +lisp-object+)
4262                          (when (eq representation :unboxed-fixnum)
4263                            (emit-unbox-fixnum))
4264                          (emit-move-from-stack target representation))))
4265               (return-from p2-logand t))))))
4266  (dformat t "p2-logand default case~%")
4267  (compile-function-call form target representation))
4268
4269(defun p2-mod (form &key (target :stack) representation)
4270  (unless (check-arg-count form 2)
4271    (compile-function-call form target representation)
4272    (return-from p2-mod))
4273  (let* ((args (cdr form))
4274         (arg1 (car args))
4275         (arg2 (cadr args)))
4276    (cond ((fixnump arg2)
4277           (compile-form arg1 :target :stack)
4278           (maybe-emit-clear-values arg1)
4279           (emit-push-constant-int arg2)
4280           (emit-invokevirtual +lisp-object-class+ "MOD" '("I") +lisp-object+))
4281          (t
4282           (compile-form arg1 :target :stack)
4283           (compile-form arg2 :target :stack)
4284           (unless (and (single-valued-p arg1)
4285                        (single-valued-p arg2))
4286             (emit-clear-values))
4287           (emit-invokevirtual +lisp-object-class+ "MOD" (list +lisp-object+) +lisp-object+)))
4288    (when (eq representation :unboxed-fixnum)
4289      (emit-unbox-fixnum))
4290    (emit-move-from-stack target representation)))
4291
4292(defun p2-zerop (form &key (target :stack) representation)
4293  (unless (check-arg-count form 1)
4294    (compile-function-call form target representation)
4295    (return-from p2-zerop))
4296  (let* ((arg (cadr form))
4297         (var (unboxed-fixnum-variable arg)))
4298    (cond ((subtypep (derive-type arg) 'FIXNUM)
4299           (compile-form arg :target :stack :representation :unboxed-fixnum)
4300           (let ((LABEL1 (gensym))
4301                 (LABEL2 (gensym)))
4302             (emit 'ifne LABEL1)
4303             (emit-push-t)
4304             (emit 'goto LABEL2)
4305             (label LABEL1)
4306             (emit-push-nil)
4307             (label LABEL2)
4308             (emit-move-from-stack target)))
4309          (t
4310           (compile-form arg :target :stack)
4311           (maybe-emit-clear-values arg)
4312           (emit-invoke-method "ZEROP" target representation)))))
4313
4314(defun derive-type (form)
4315  (cond ((fixnump form)
4316         (return-from derive-type 'fixnum))
4317        ((unboxed-fixnum-variable form)
4318         (return-from derive-type 'fixnum))
4319        ((consp form)
4320         (let ((op (first form)))
4321           (case op
4322             (ASH
4323              (dformat t "derive-type ASH case form = ~S~%" form)
4324              (let* ((arg1 (second form))
4325                     (var1 (unboxed-fixnum-variable arg1))
4326                     (arg2 (third form)))
4327                (dformat t "derive-type ASH case var1 = ~S~%" var1)
4328                (when (and var1 (fixnump arg2) (minusp arg2))
4329                  (return-from derive-type 'FIXNUM))))
4330             (THE
4331              (dformat t "derive-type THE case form = ~S~%" form)
4332              (when (subtypep (second form) 'FIXNUM)
4333                (dformat t "derive-type THE case form = ~S returning FIXNUM~%" form)
4334                (return-from derive-type 'FIXNUM)))))))
4335  t)
4336
4337(defun p2-length (form &key (target :stack) representation)
4338  (unless (check-arg-count form 1)
4339    (compile-function-call form target representation)
4340    (return-from p2-length))
4341  (let ((arg (cadr form)))
4342    (compile-form arg :target :stack)
4343    (maybe-emit-clear-values arg)
4344    (cond ((eq representation :unboxed-fixnum)
4345           (emit-invokevirtual +lisp-object-class+ "length" nil "I"))
4346          (t
4347           (emit-invokevirtual +lisp-object-class+ "LENGTH" nil +lisp-object+)))
4348    (emit-move-from-stack target representation)))
4349
4350(defun compile-nth (form &key (target :stack) representation)
4351  (unless (check-arg-count form 2)
4352    (compile-function-call form target representation)
4353    (return-from compile-nth))
4354  (let ((index-form (second form))
4355        (list-form (third form)))
4356    (compile-form index-form :target :stack :representation :unboxed-fixnum)
4357    (compile-form list-form :target :stack)
4358    (unless (and (single-valued-p index-form)
4359                 (single-valued-p list-form))
4360      (emit-clear-values))
4361    (emit 'swap)
4362    (emit-invokevirtual +lisp-object-class+ "NTH" '("I") +lisp-object+)
4363    (when (eq representation :unboxed-fixnum)
4364      (emit-unbox-fixnum))
4365    (emit-move-from-stack target representation)))
4366
4367(defun p2-times (form &key (target :stack) representation)
4368  (case (length form)
4369    (3
4370     (let* ((args (cdr form))
4371            (arg1 (first args))
4372            (arg2 (second args)))
4373       (dformat t "p2-times form = ~S~%" form)
4374       (when (fixnump arg1)
4375         (dformat t "p2-times arg1 is a fixnum, swapping...~%")
4376         (rotatef arg1 arg2)
4377         (dformat t "arg1 => ~S~%" arg1)
4378         (dformat t "arg2 => ~S~%" arg2))
4379       (cond ((fixnump arg2)
4380              (dformat t "p2-times case 1~%")
4381              (compile-form arg1 :target :stack)
4382              (maybe-emit-clear-values arg1)
4383              (emit-push-int arg2)
4384              (emit-invokevirtual +lisp-object-class+ "multiplyBy" '("I") +lisp-object+)
4385              (when (eq representation :unboxed-fixnum)
4386                (emit-unbox-fixnum))
4387              (emit-move-from-stack target representation))
4388             (t
4389              (dformat t "p2-times default case~%")
4390              (compile-binary-operation "multiplyBy" args target representation)))))
4391    (t
4392     (compile-function-call form target representation))))
4393
4394(defun p2-plus (form &key (target :stack) representation)
4395  (case (length form)
4396    (3
4397     (let* ((args (cdr form))
4398            (arg1 (first args))
4399            (arg2 (second args))
4400            (var1 (unboxed-fixnum-variable arg1))
4401            (var2 (unboxed-fixnum-variable arg2)))
4402       (dformat t "p2-plus form = ~S~%" form)
4403       (when (fixnump arg1)
4404         (dformat t "p2-plus arg1 is a fixnum, swapping...~%")
4405         (rotatef arg1 arg2)
4406         (rotatef var1 var2)
4407         (dformat t "arg1 => ~S~%" arg1)
4408         (dformat t "arg2 => ~S~%" arg2))
4409       (cond ((and (numberp arg1) (numberp arg2))
4410              (compile-constant (+ arg1 arg2)
4411                                :target target
4412                                :representation representation))
4413             ((and var1 var2)
4414              (dformat t "p2-plus case 1~%")
4415              (dformat t "target = ~S representation = ~S~%" target representation)
4416              (aver (variable-register var1))
4417              (aver (variable-register var2))
4418              (when target
4419                (cond ((eq representation :unboxed-fixnum)
4420                       (emit-push-int var1)
4421                       (emit-push-int arg2)
4422                       (emit 'iadd))
4423                      (t
4424                       (emit-push-long var1)
4425                       (emit-push-long var2)
4426                       (emit 'ladd)
4427                       (emit-box-long)))
4428                (emit-move-from-stack target representation)))
4429             ((and var1 (fixnump arg2))
4430              (dformat t "p2-plus case 2~%")
4431              (aver (variable-register var1))
4432              (cond ((eq representation :unboxed-fixnum)
4433                     (emit-push-int var1)
4434                     (emit-push-int arg2)
4435                     (emit 'iadd))
4436                    (t
4437                     (emit-push-long var1)
4438                     (emit-push-long arg2)
4439                     (emit 'ladd)
4440                     (emit-box-long)))
4441              (emit-move-from-stack target representation))
4442             ((and (fixnump arg1) var2)
4443              (dformat t "p2-plus case 3~%")
4444              (aver (variable-register var2))
4445              (cond ((eq representation :unboxed-fixnum)
4446                     (emit-push-int arg1)
4447                     (emit-push-int var2)
4448                     (emit 'iadd))
4449                    (t
4450                     (emit-push-long arg1)
4451                     (emit-push-long var2)
4452                     (emit 'ladd)
4453                     (emit-box-long)))
4454              (emit-move-from-stack target representation))
4455             ((eql arg1 1)
4456              (dformat t "p2-plus case 4~%")
4457              (compile-form arg2 :target :stack)
4458              (maybe-emit-clear-values arg2)
4459              (emit-invoke-method "incr" target representation))
4460             ((eql arg2 1)
4461              (dformat t "p2-plus case 5~%")
4462              (cond ((and (eq representation :unboxed-fixnum)
4463                          (subtypep (derive-type arg1) 'FIXNUM))
4464                     (compile-form arg1 :target :stack :representation :unboxed-fixnum)
4465                     (maybe-emit-clear-values arg1)
4466                     (emit-push-int 1)
4467                     (emit 'iadd)
4468                     (emit-move-from-stack target representation))
4469                    (t
4470                     (compile-form arg1 :target :stack)
4471                     (maybe-emit-clear-values arg1)
4472                     (emit-invoke-method "incr" target representation))))
4473             ((arg-is-fixnum-p arg1)
4474              (dformat t "p2-plus case 6~%")
4475              (emit-push-int arg1)
4476              (compile-form arg2 :target :stack)
4477              (maybe-emit-clear-values arg2)
4478              (emit 'swap)
4479              (emit-invokevirtual +lisp-object-class+ "add" '("I") +lisp-object+)
4480              (when (eq representation :unboxed-fixnum)
4481                (emit-unbox-fixnum))
4482              (emit-move-from-stack target representation))
4483             ((arg-is-fixnum-p arg2)
4484              (dformat t "p2-plus case 7~%")
4485              (compile-form arg1 :target :stack)
4486              (maybe-emit-clear-values arg1)
4487              (emit-push-int arg2)
4488              (emit-invokevirtual +lisp-object-class+ "add" '("I") +lisp-object+)
4489              (when (eq representation :unboxed-fixnum)
4490                (emit-unbox-fixnum))
4491              (emit-move-from-stack target representation))
4492             ((and (consp arg1)
4493                   (eq (car arg1) 'THE)
4494                   (subtypep (cadr arg1) 'FIXNUM)
4495                   (consp arg2)
4496                   (eq (car arg2) 'THE)
4497                   (subtypep (cadr arg2) 'FIXNUM))
4498              (dformat t "p2-plus case 7b representation = ~S~%" representation)
4499              (let ((must-clear-values nil))
4500                (compile-form arg1 :target :stack :representation :unboxed-fixnum)
4501                (unless (single-valued-p arg1)
4502                  (dformat t "not single-valued: ~S~%" arg1)
4503                  (setf must-clear-values t))
4504                (unless (eq representation :unboxed-fixnum)
4505                  (emit 'i2l))
4506                (compile-form arg2 :target :stack :representation :unboxed-fixnum)
4507                (setf must-clear-values (or must-clear-values
4508                                            (not (single-valued-p arg2))))
4509                (cond ((eq representation :unboxed-fixnum)
4510                       (emit 'iadd))
4511                      (t
4512                       (emit 'i2l)
4513                       (emit 'ladd)
4514                       (emit-box-long)))
4515                (when must-clear-values
4516                  (dformat t "p2-plus case 7b calling emit-clear-values~%")
4517                  (emit-clear-values))
4518                (emit-move-from-stack target representation)))
4519             (t
4520              (dformat t "p2-plus case 8 ~S~%" form)
4521              (compile-binary-operation "add" args target representation)))))
4522    (4
4523     (dformat t "p2-plus case 9~%")
4524     ;; (+ a b c) => (+ (+ a b) c)
4525     (let ((new-form `(+ (+ ,(second form) ,(third form)) ,(fourth form))))
4526       (dformat t "form = ~S~%" form)
4527       (dformat t "new-form = ~S~%" new-form)
4528       (p2-plus new-form :target target :representation representation)))
4529    (t
4530     (dformat t "p2-plus case 10~%")
4531     (compile-function-call form target representation))))
4532
4533(defun p2-minus (form &key (target :stack) representation)
4534  (case (length form)
4535    (3
4536     (let* ((args (cdr form))
4537            (arg1 (first args))
4538            (arg2 (second args))
4539            (var1 (unboxed-fixnum-variable arg1))
4540            (var2 (unboxed-fixnum-variable arg2)))
4541       (cond ((and (numberp arg1) (numberp arg2))
4542              (compile-constant (- arg1 arg2)
4543                                :target target
4544                                :representation representation))
4545             ((and var1 var2)
4546              (dformat t "p2-minus case 1~%")
4547              (aver (variable-register var1))
4548              (aver (variable-register var2))
4549              (when target
4550                (cond
4551                 ((eq representation :unboxed-fixnum)
4552                  (emit 'iload (variable-register var1))
4553                  (emit 'iload (variable-register var2))
4554                  (emit 'isub))
4555                 (t
4556;;                   (emit 'iload (variable-register var1))
4557;;                   (emit 'i2l)
4558                  (emit-push-long var1)
4559;;                   (emit 'iload (variable-register var2))
4560;;                   (emit 'i2l)
4561                  (emit-push-long var2)
4562                  (emit 'lsub)
4563                  (emit-box-long)))
4564                (emit-move-from-stack target representation)))
4565             ((and var1 (fixnump arg2))
4566              (dformat t "p2-minus case 2 ~S ~S~%" form representation)
4567              (aver (variable-register var1))
4568              (cond ((eq representation :unboxed-fixnum)
4569                     (dformat t "p2-minus case 2 ISUB~%")
4570                     (emit-push-int var1)
4571                     (emit-push-int arg2)
4572                     (emit 'isub))
4573                    (t
4574                     (dformat t "p2-minus case 2 LSUB~%")
4575                     (emit-push-long var1)
4576                     (emit-push-long arg2)
4577                     (emit 'lsub)
4578                     (emit-box-long)))
4579              (emit-move-from-stack target representation))
4580             ((and (fixnump arg1) var2)
4581              (dformat t "p2-minus case 3~%")
4582              (aver (variable-register var2))
4583              (cond ((eq representation :unboxed-fixnum)
4584