source: branches/0.24.x/abcl/src/org/armedbear/lisp/jvm.lisp

Last change on this file was 13120, checked in by ehuelsmann, 15 years ago

Improve parent/child block relationship tracking;
Improve block-finding;
Untabify (sorry to mix that!).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 26.9 KB
Line 
1;;; jvm.lisp
2;;;
3;;; Copyright (C) 2003-2008 Peter Graves
4;;; $Id: jvm.lisp 13120 2011-01-03 12:09:37Z ehuelsmann $
5;;;
6;;; This program is free software; you can redistribute it and/or
7;;; modify it under the terms of the GNU General Public License
8;;; as published by the Free Software Foundation; either version 2
9;;; of the License, or (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19;;;
20;;; As a special exception, the copyright holders of this library give you
21;;; permission to link this library with independent modules to produce an
22;;; executable, regardless of the license terms of these independent
23;;; modules, and to copy and distribute the resulting executable under
24;;; terms of your choice, provided that you also meet, for each linked
25;;; independent module, the terms and conditions of the license of that
26;;; module.  An independent module is a module which is not derived from
27;;; or based on this library.  If you modify this library, you may extend
28;;; this exception to your version of the library, but you are not
29;;; obligated to do so.  If you do not wish to do so, delete this
30;;; exception statement from your version.
31
32(in-package "JVM")
33
34(export '(compile-defun *catch-errors* jvm-compile-package
35          derive-compiler-type))
36
37(eval-when (:compile-toplevel :load-toplevel :execute)
38  (require "LOOP")
39  (require "FORMAT")
40  (require "CLOS")
41  (require "PRINT-OBJECT")
42  (require "COMPILER-TYPES")
43  (require "COMPILER-ERROR")
44  (require "KNOWN-FUNCTIONS")
45  (require "DUMP-FORM")
46  (require "JVM-INSTRUCTIONS")
47  (require "JVM-CLASS-FILE")
48  (require "KNOWN-SYMBOLS")
49  (require "JAVA")
50  (require "COMPILER-PASS1")
51  (require "COMPILER-PASS2"))
52
53(defvar *closure-variables* nil)
54
55(defvar *enable-dformat* nil)
56
57#+nil
58(defun dformat (destination control-string &rest args)
59  (when *enable-dformat*
60    (apply #'sys::%format destination control-string args)))
61
62(defmacro dformat (&rest ignored)
63  (declare (ignore ignored)))
64
65(declaim (inline u2 s1 s2))
66
67(defknown u2 (fixnum) cons)
68(defun u2 (n)
69  (declare (optimize speed))
70  (declare (type (unsigned-byte 16) n))
71  (when (not (<= 0 n 65535))
72    (error "u2 argument ~A out of 65k range." n))
73  (list (logand (ash n -8) #xff)
74        (logand n #xff)))
75
76(defknown s1 (fixnum) fixnum)
77(defun s1 (n)
78  (declare (optimize speed))
79  (declare (type (signed-byte 8) n))
80  (when (not (<= -128 n 127))
81    (error "s2 argument ~A out of 16-bit signed range." n))
82  (if (< n 0)
83      (1+ (logxor (- n) #xFF))
84      n))
85
86
87(defknown s2 (fixnum) cons)
88(defun s2 (n)
89  (declare (optimize speed))
90  (declare (type (signed-byte 16) n))
91  (when (not (<= -32768 n 32767))
92    (error "s2 argument ~A out of 16-bit signed range." n))
93  (u2 (if (< n 0) (1+ (logxor (- n) #xFFFF))
94          n)))
95
96
97
98
99
100(defmacro with-saved-compiler-policy (&body body)
101  "Saves compiler policy variables, restoring them after evaluating `body'."
102  `(let ((*speed* *speed*)
103         (*space* *space*)
104         (*safety* *safety*)
105         (*debug* *debug*)
106         (*explain* *explain*)
107         (*inline-declarations* *inline-declarations*))
108     ,@body))
109
110
111
112(defvar *compiler-debug* nil)
113
114(defvar *pool* nil)
115(defvar *static-code* ())
116(defvar *class-file* nil)
117
118(defvar *externalized-objects* nil)
119(defvar *declared-functions* nil)
120
121(defstruct (abcl-class-file (:include class-file)
122                            (:constructor %make-abcl-class-file))
123  pathname ; pathname of output file
124  class-name
125  lambda-name
126  lambda-list ; as advertised
127  static-initializer
128  constructor
129  objects ;; an alist of externalized objects and their field names
130  (functions (make-hash-table :test 'equal)) ;; because of (SETF ...) functions
131  )
132
133(defun class-name-from-filespec (filespec)
134  (let* ((name (pathname-name filespec)))
135    (declare (type string name))
136    (dotimes (i (length name))
137      (declare (type fixnum i))
138      (when (or (char= (char name i) #\-)
139                (char= (char name i) #\Space))
140        (setf (char name i) #\_)))
141    (make-jvm-class-name
142     (concatenate 'string "org.armedbear.lisp." name))))
143
144(defun make-unique-class-name ()
145  "Creates a random class name for use with a `class-file' structure's
146`class' slot."
147  (make-jvm-class-name
148   (concatenate 'string "abcl_"
149                (substitute #\_ #\-
150                            (java:jcall (java:jmethod "java.util.UUID"
151                                                      "toString")
152                                        (java:jstatic "randomUUID"
153                                                      "java.util.UUID"))))))
154
155(defun make-abcl-class-file (&key pathname lambda-name lambda-list)
156  "Creates a `class-file' structure. If `pathname' is non-NIL, it's
157used to derive a class name. If it is NIL, a random one created
158using `make-unique-class-name'."
159  (let* ((class-name (if pathname
160                         (class-name-from-filespec  pathname)
161                         (make-unique-class-name)))
162         (class-file (%make-abcl-class-file :pathname pathname
163                                            :class class-name ; to be finalized
164                                            :class-name class-name
165                                            :lambda-name lambda-name
166                                            :lambda-list lambda-list
167                                            :access-flags '(:public :final))))
168    (when *file-compilation*
169      (let ((source-attribute
170             (make-source-file-attribute
171              :filename (file-namestring *compile-file-truename*))))
172        (class-add-attribute class-file source-attribute)))
173    class-file))
174
175(defmacro with-class-file (class-file &body body)
176  (let ((var (gensym)))
177    `(let* ((,var                   ,class-file)
178            (*class-file*           ,var)
179            (*pool*                 (abcl-class-file-constants ,var))
180            (*externalized-objects* (abcl-class-file-objects ,var))
181            (*declared-functions*   (abcl-class-file-functions ,var)))
182       (progn ,@body)
183       (setf (abcl-class-file-objects ,var)      *externalized-objects*
184             (abcl-class-file-functions ,var)    *declared-functions*))))
185
186(defstruct compiland
187  name
188  lambda-expression
189  arg-vars          ; variables for lambda arguments
190  free-specials     ;
191  arity             ; number of args, or NIL if the number of args can vary.
192  p1-result         ; the parse tree as created in pass 1
193  parent            ; the parent for compilands which defined within another
194  (children 0       ; Number of local functions
195            :type fixnum) ; defined with FLET, LABELS or LAMBDA
196  blocks            ; TAGBODY, PROGV, BLOCK, etc. blocks
197  argument-register
198  closure-register
199  environment-register
200  class-file ; class-file object
201  (%single-valued-p t))
202
203(defknown compiland-single-valued-p (t) t)
204(defun compiland-single-valued-p (compiland)
205  (unless (compiland-parent compiland)
206    (let ((name (compiland-name compiland)))
207      (when name
208        (let ((result-type
209               (or (function-result-type name)
210                   (and (proclaimed-ftype name)
211                        (ftype-result-type (proclaimed-ftype name))))))
212          (when result-type
213            (return-from compiland-single-valued-p
214                         (cond ((eq result-type '*)
215                                nil)
216                               ((atom result-type)
217                                t)
218                               ((eq (%car result-type) 'VALUES)
219                                (= (length result-type) 2))
220                               (t
221                                t))))))))
222  ;; Otherwise...
223  (compiland-%single-valued-p compiland))
224
225(defvar *current-compiland* nil)
226
227(defvar *this-class* nil)
228
229;; All tags visible at the current point of compilation, some of which may not
230;; be in the current compiland.
231(defvar *visible-tags* ())
232
233;; The next available register.
234(defvar *register* 0)
235
236;; Total number of registers allocated.
237(defvar *registers-allocated* 0)
238
239;; Variables visible at the current point of compilation.
240(defvar *visible-variables* nil
241  "All variables visible to the form currently being
242processed, including free specials.")
243
244;; All variables seen so far.
245(defvar *all-variables* nil
246  "All variables in the lexical scope (thus excluding free specials)
247of the compilands being processed (p1: so far; p2: in total).")
248
249;; Undefined variables that we've already warned about.
250(defvar *undefined-variables* nil)
251
252(defvar *dump-variables* nil)
253
254(defun dump-1-variable (variable)
255  (sys::%format t "  ~S special-p = ~S register = ~S binding-reg = ~S index = ~S declared-type = ~S~%"
256           (variable-name variable)
257           (variable-special-p variable)
258           (variable-register variable)
259           (variable-binding-register variable)
260           (variable-index variable)
261           (variable-declared-type variable)))
262
263(defun dump-variables (list caption &optional (force nil))
264  (when (or force *dump-variables*)
265    (write-string caption)
266    (if list
267        (dolist (variable list)
268          (dump-1-variable variable))
269        (sys::%format t "  None.~%"))))
270
271(defstruct (variable-info (:conc-name variable-)
272                          (:constructor make-variable)
273                          (:predicate variable-p))
274  name
275  initform
276  (declared-type :none)
277  (derived-type :none)
278  ignore-p
279  ignorable-p
280  representation
281  special-p     ; indicates whether a variable is special
282  register      ; register number for a local variable
283  binding-register ; register number containing the binding reference
284  index         ; index number for a variable in the argument array
285  closure-index ; index number for a variable in the closure context array
286  environment   ; the environment for the variable, if we're compiling in
287                ; a non-null lexical environment with variables
288    ;; a variable can be either special-p *or* have a register *or*
289    ;; have an index *or* a closure-index *or* an environment
290  (reads 0 :type fixnum)
291  (writes 0 :type fixnum)
292  references
293  (references-allowed-p t) ; NIL if this is a symbol macro in the enclosing
294                           ; lexical environment
295  used-non-locally-p
296  (compiland *current-compiland*)
297  block)
298
299(defstruct (var-ref (:constructor make-var-ref (variable)))
300  ;; The variable this reference refers to. Will be NIL if the VAR-REF has been
301  ;; rewritten to reference a constant value.
302  variable
303  ;; True if the VAR-REF has been rewritten to reference a constant value.
304  constant-p
305  ;; The constant value of this VAR-REF.
306  constant-value)
307
308;; obj can be a symbol or variable
309;; returns variable or nil
310(declaim (ftype (function (t) t) unboxed-fixnum-variable))
311(defun unboxed-fixnum-variable (obj)
312  (cond ((symbolp obj)
313         (let ((variable (find-visible-variable obj)))
314           (if (and variable
315                    (eq (variable-representation variable) :int))
316               variable
317               nil)))
318        ((variable-p obj)
319         (if (eq (variable-representation obj) :int)
320             obj
321             nil))
322        (t
323         nil)))
324
325(defvar *child-p* nil
326  "True for local functions created by FLET, LABELS and (NAMED-)LAMBDA")
327
328(defknown find-variable (symbol list) t)
329(defun find-variable (name variables)
330  (dolist (variable variables)
331    (when (eq name (variable-name variable))
332      (return variable))))
333
334(defknown find-visible-variable (t) t)
335(defun find-visible-variable (name)
336  (dolist (variable *visible-variables*)
337    (when (eq name (variable-name variable))
338      (return variable))))
339
340(defknown allocate-register () (integer 0 65535))
341(defun allocate-register ()
342  (let* ((register *register*)
343         (next-register (1+ register)))
344    (declare (type (unsigned-byte 16) register next-register))
345    (setf *register* next-register)
346    (when (< *registers-allocated* next-register)
347      (setf *registers-allocated* next-register))
348    register))
349
350(defknown allocate-register-pair () (integer 0 65535))
351(defun allocate-register-pair ()
352  (let* ((register *register*)
353         (next-register (+ register 2)))
354    (declare (type (unsigned-byte 16) register next-register))
355    (setf *register* next-register)
356    (when (< *registers-allocated* next-register)
357      (setf *registers-allocated* next-register))
358    register))
359
360(defstruct local-function
361  name
362  definition
363  compiland
364  inline-expansion
365  function    ;; the function loaded through load-compiled-function
366  class-file  ;; the class file structure for this function
367  variable    ;; the variable which contains the loaded compiled function
368              ;; or compiled closure
369  environment ;; the environment in which the function is stored in
370              ;; case of a function from an enclosing lexical environment
371              ;; which itself isn't being compiled
372  (references-allowed-p t) ;;whether a reference to the function CAN be captured
373  (references-needed-p nil) ;;whether a reference to the function NEEDS to be
374                            ;;captured, because the function name is used in a
375                            ;;(function ...) form. Obviously implies
376                            ;;references-allowed-p.
377  )
378
379(defvar *local-functions* ())
380
381(defknown find-local-function (t) t)
382(defun find-local-function (name)
383  (dolist (local-function *local-functions* nil)
384    (when (equal name (local-function-name local-function))
385        (return local-function))))
386
387(defvar *using-arg-array* nil)
388(defvar *hairy-arglist-p* nil)
389
390
391(defvar *block* nil
392  "The innermost block applicable to the current lexical environment.")
393(defvar *blocks* ()
394  "The list of blocks in effect in the current lexical environment.
395
396The top node does not need to be equal to the value of `*block*`. E.g.
397when processing the bindings of a LET form, `*block*` is bound to the node
398of that LET, while the block is not considered 'in effect': that only happens
399until the body is being processed.")
400
401(defstruct node
402  form
403  children
404  (compiland *current-compiland*))
405;; No need for a special constructor: nobody instantiates
406;; nodes directly
407
408(declaim (inline add-node-child))
409(defun add-node-child (parent child)
410  "Add a child node to the `children` list of a parent node,
411if that parent belongs to the same compiland."
412  (when parent
413    (when (eq (node-compiland parent) *current-compiland*)
414      (push child (node-children parent)))))
415
416;; control-transferring blocks: TAGBODY, CATCH, to do: BLOCK
417
418(defstruct (control-transferring-node (:include node))
419  ;; If non-nil, the TAGBODY contains local blocks which "contaminate" the
420  ;; environment, with GO forms in them which target tags in this TAGBODY
421  ;; Non-nil if and only if the block doesn't modify the environment
422  needs-environment-restoration
423  )
424;; No need for a special constructor: nobody instantiates
425;; control-transferring-nodes directly
426
427(defstruct (tagbody-node (:conc-name tagbody-)
428                         (:include control-transferring-node)
429                         (:constructor %make-tagbody-node ()))
430  ;; True if a tag in this tagbody is the target of a non-local GO.
431  non-local-go-p
432  ;; Tags in the tagbody form; a list of tag structures
433  tags
434  ;; Contains a variable whose value uniquely identifies the
435  ;; lexical scope from this block, to be used by GO
436  id-variable)
437(defknown make-tagbody-node () t)
438(defun make-tagbody-node ()
439  (let ((block (%make-tagbody-node)))
440    (push block (compiland-blocks *current-compiland*))
441    (add-node-child *block* block)
442    block))
443
444(defstruct (catch-node (:conc-name catch-)
445                       (:include control-transferring-node)
446                       (:constructor %make-catch-node ()))
447  ;; The catch tag-form is evaluated, meaning we
448  ;; have no predefined value to store here
449  )
450(defknown make-catch-node () t)
451(defun make-catch-node ()
452  (let ((block (%make-catch-node)))
453    (push block (compiland-blocks *current-compiland*))
454    (add-node-child *block* block)
455    block))
456
457(defstruct (block-node (:conc-name block-)
458                       (:include control-transferring-node)
459                       (:constructor %make-block-node (name)))
460  name  ;; Block name
461  (exit (gensym))
462  target
463  ;; True if there is a non-local RETURN from this block.
464  non-local-return-p
465  ;; Contains a variable whose value uniquely identifies the
466  ;; lexical scope from this block, to be used by RETURN-FROM
467  id-variable)
468(defknown make-block-node (t) t)
469(defun make-block-node (name)
470  (let ((block (%make-block-node name)))
471    (push block (compiland-blocks *current-compiland*))
472    (add-node-child *block* block)
473    block))
474
475;; binding blocks: LET, LET*, FLET, LABELS, M-V-B, PROGV, LOCALLY
476;;
477;; Binding blocks can carry references to local (optionally special) variable bindings,
478;;  contain free special bindings or both
479
480(defstruct (binding-node (:include node))
481  ;; number of the register of the saved dynamic env, or NIL if none
482  environment-register
483  ;; Not used for LOCALLY and FLET; LABELS uses vars to store its functions
484  vars
485  free-specials)
486;; nobody instantiates any binding nodes directly, so there's no reason
487;; to create a constructor with the approprate administration code
488
489(defstruct (let/let*-node (:conc-name let-)
490                          (:include binding-node)
491                          (:constructor %make-let/let*-node ())))
492(defknown make-let/let*-node () t)
493(defun make-let/let*-node ()
494  (let ((block (%make-let/let*-node)))
495    (push block (compiland-blocks *current-compiland*))
496    (add-node-child *block* block)
497    block))
498
499(defstruct (flet-node (:conc-name flet-)
500                      (:include binding-node)
501                      (:constructor %make-flet-node ())))
502(defknown make-flet-node () t)
503(defun make-flet-node ()
504  (let ((block (%make-flet-node)))
505    (push block (compiland-blocks *current-compiland*))
506    (add-node-child *block* block)
507    block))
508
509(defstruct (labels-node (:conc-name labels-)
510                        (:include binding-node)
511                        (:constructor %make-labels-node ())))
512(defknown make-labels-node () t)
513(defun make-labels-node ()
514  (let ((block (%make-labels-node)))
515    (push block (compiland-blocks *current-compiland*))
516    (add-node-child *block* block)
517    block))
518
519(defstruct (m-v-b-node (:conc-name m-v-b-)
520                       (:include binding-node)
521                       (:constructor %make-m-v-b-node ())))
522(defknown make-m-v-b-node () t)
523(defun make-m-v-b-node ()
524  (let ((block (%make-m-v-b-node)))
525    (push block (compiland-blocks *current-compiland*))
526    (add-node-child *block* block)
527    block))
528
529(defstruct (progv-node (:conc-name progv-)
530                       (:include binding-node)
531                       (:constructor %make-progv-node ())))
532(defknown make-progv-node () t)
533(defun make-progv-node ()
534  (let ((block (%make-progv-node)))
535    (push block (compiland-blocks *current-compiland*))
536    block))
537
538(defstruct (locally-node (:conc-name locally-)
539                         (:include binding-node)
540                         (:constructor %make-locally-node ())))
541(defknown make-locally-node () t)
542(defun make-locally-node ()
543  (let ((block (%make-locally-node)))
544    (push block (compiland-blocks *current-compiland*))
545    (add-node-child *block* block)
546    block))
547
548;; blocks requiring non-local exits: UNWIND-PROTECT, SYS:SYNCHRONIZED-ON
549
550(defstruct (protected-node (:include node)
551                           (:constructor %make-protected-node ())))
552(defknown make-protected-node () t)
553(defun make-protected-node ()
554  (let ((block (%make-protected-node)))
555    (push block (compiland-blocks *current-compiland*))
556    (add-node-child *block* block)
557    block))
558
559(defstruct (unwind-protect-node (:conc-name unwind-protect-)
560                                (:include protected-node)
561                                (:constructor %make-unwind-protect-node ())))
562(defknown make-unwind-protect-node () t)
563(defun make-unwind-protect-node ()
564  (let ((block (%make-unwind-protect-node)))
565    (push block (compiland-blocks *current-compiland*))
566    (add-node-child *block* block)
567    block))
568
569(defstruct (synchronized-node (:conc-name synchronized-)
570                              (:include protected-node)
571                              (:constructor %make-synchronized-node ())))
572(defknown make-synchronized-node () t)
573(defun make-synchronized-node ()
574  (let ((block (%make-synchronized-node)))
575    (push block (compiland-blocks *current-compiland*))
576    (add-node-child *block* block)
577    block))
578
579(defun find-block (name)
580  (dolist (block *blocks*)
581    (when (and (block-node-p block)
582               (eq name (block-name block)))
583      (return block))))
584
585(defun %find-enclosed-blocks (form)
586  "Helper function for `find-enclosed-blocks`, implementing the actual
587algorithm specified there."
588  (cond
589   ((node-p form) (list form))
590   ((atom form) nil)
591   (t
592    ;; We can't use MAPCAN or DOLIST here: they'll choke on dotted lists
593    (do* ((tail form (cdr tail))
594          blocks)
595         ((null tail) blocks)
596      (setf blocks
597            (nconc (%find-enclosed-blocks (if (consp tail)
598                                              (car tail) tail))
599                   blocks))
600      (when (not (listp tail))
601        (return blocks))))))
602
603(defun find-enclosed-blocks (form)
604  "Returns the immediate enclosed blocks by searching the form's subforms.
605
606More deeply nested blocks can be reached through the `node-children`
607field of the immediate enclosed blocks."
608  (when *blocks*
609    ;; when the innermost enclosing block doesn't have node-children,
610    ;;  there's really nothing to search for.
611    (when (null (node-children (car *blocks*)))
612      (return-from find-enclosed-blocks)))
613
614  (%find-enclosed-blocks form))
615   
616
617(defun some-nested-block (predicate blocks)
618  "Applies `predicate` recursively to the `blocks` and its children,
619until predicate returns non-NIL, returning that value.
620
621`blocks` may be a single block or a list of blocks."
622  (when blocks
623    (some #'(lambda (b)
624              (or (funcall predicate b)
625                  (some-nested-block predicate (node-children b))))
626          (if (listp blocks)
627              blocks
628            (list blocks)))))
629
630(defknown node-constant-p (t) boolean)
631(defun node-constant-p (object)
632  (cond ((node-p object)
633         nil)
634        ((var-ref-p object)
635         nil)
636        ((constantp object)
637         t)
638        (t
639         nil)))
640
641(defknown block-requires-non-local-exit-p (t) boolean)
642(defun block-requires-non-local-exit-p (object)
643  "A block which *always* requires a 'non-local-exit' is a block which
644requires a transfer control exception to be thrown: e.g. Go and Return.
645
646Non-local exits are required by blocks which do more in their cleanup
647than just restore the lastSpecialBinding (= dynamic environment).
648"
649  (or (unwind-protect-node-p object)
650      (catch-node-p object)
651      (synchronized-node-p object)))
652
653(defun block-opstack-unsafe-p (block)
654  (or (when (tagbody-node-p block) (tagbody-non-local-go-p block))
655      (when (block-node-p block) (block-non-local-return-p block))
656      (catch-node-p block)))
657
658(defknown block-creates-runtime-bindings-p (t) boolean)
659(defun block-creates-runtime-bindings-p (block)
660  ;; FIXME: This may be false, if the bindings to be
661  ;; created are a quoted list
662  (progv-node-p block))
663
664(defknown enclosed-by-runtime-bindings-creating-block-p (t) boolean)
665(defun enclosed-by-runtime-bindings-creating-block-p (outermost-block)
666  "Indicates whether the code being compiled/analyzed is enclosed in a
667block which creates special bindings at runtime."
668  (dolist (enclosing-block *blocks*)
669    (when (eq enclosing-block outermost-block)
670      (return-from enclosed-by-runtime-bindings-creating-block-p nil))
671    (when (block-creates-runtime-bindings-p enclosing-block)
672      (return-from enclosed-by-runtime-bindings-creating-block-p t))))
673
674(defknown enclosed-by-protected-block-p (&optional t) boolean)
675(defun enclosed-by-protected-block-p (&optional outermost-block)
676  "Indicates whether the code being compiled/analyzed is enclosed in
677a block which requires a non-local transfer of control exception to
678be generated.
679"
680  (dolist (enclosing-block *blocks*)
681    (when (eq enclosing-block outermost-block)
682      (return-from enclosed-by-protected-block-p nil))
683    (when (block-requires-non-local-exit-p enclosing-block)
684      (return-from enclosed-by-protected-block-p t))))
685
686(defknown enclosed-by-environment-setting-block-p (&optional t) boolean)
687(defun enclosed-by-environment-setting-block-p (&optional outermost-block)
688  (dolist (enclosing-block *blocks*)
689    (when (eq enclosing-block outermost-block)
690      (return nil))
691    (when (and (binding-node-p enclosing-block)
692               (binding-node-environment-register enclosing-block))
693      (return t))))
694
695(defknown environment-register-to-restore (&optional t) t)
696(defun environment-register-to-restore (&optional outermost-block)
697  "Returns the environment register which contains the
698saved environment from the outermost enclosing block:
699
700That's the one which contains the environment used in the outermost block."
701  (flet ((outermost-register (last-register block)
702           (when (eq block outermost-block)
703             (return-from environment-register-to-restore last-register))
704           (or (and (binding-node-p block)
705                    (binding-node-environment-register block))
706               last-register)))
707    (reduce #'outermost-register *blocks*
708            :initial-value nil)))
709
710(defstruct tag
711  ;; The symbol (or integer) naming the tag
712  name
713  ;; The symbol which is the jump target in JVM byte code
714  label
715  ;; The associated TAGBODY
716  block
717  (compiland *current-compiland*)
718  used
719  used-non-locally)
720
721(defknown find-tag (t) t)
722(defun find-tag (name)
723  (dolist (tag *visible-tags*)
724    (when (eql name (tag-name tag))
725      (return tag))))
726
727(defun process-ignore/ignorable (declaration names variables)
728  (when (memq declaration '(IGNORE IGNORABLE))
729    (let ((what (if (eq declaration 'IGNORE) "ignored" "ignorable")))
730      (dolist (name names)
731        (unless (and (consp name) (eq (car name) 'FUNCTION))
732          (let ((variable (find-variable name variables)))
733            (cond ((null variable)
734                   (compiler-style-warn "Declaring unknown variable ~S to be ~A."
735                                        name what))
736                  ((variable-special-p variable)
737                   (compiler-style-warn "Declaring special variable ~S to be ~A."
738                                        name what))
739                  ((eq declaration 'IGNORE)
740                   (setf (variable-ignore-p variable) t))
741                  (t
742                   (setf (variable-ignorable-p variable) t)))))))))
743
744(defun finalize-generic-functions ()
745  (dolist (sym '(make-instance
746                 initialize-instance
747                 shared-initialize))
748    (let ((gf (and (fboundp sym) (fdefinition sym))))
749      (when (typep gf 'generic-function)
750        (unless (compiled-function-p gf)
751          (mop::finalize-generic-function gf))))))
752
753(finalize-generic-functions)
754
755(provide 'jvm)
Note: See TracBrowser for help on using the repository browser.